I have a template class defined like this
template<class T> class Wrap
{
/* ... */
public:
Wrap(const T&);
/* other implicit conversions */
/* ... */
};
I want to define all the comparison operators for this class outside the class like this
template<typename T> bool operator == (const Wrap<T>&, const Wrap<T>&)
{
// Do comparison here
}
This declaration however doesn't support implicit conversions of const T&
, or any other type, to const Wrap<T>&
.
So my question is how do I make it support implicit conversions when either one of the operands is of type Wrap<T>
and the other is not. I don't want to write multiple declarations of each operator for every possible permutation.
Therefore, you may not overload them outside the class, since they are not allowed to be defined outside the class in the first place.
In C++, you can't overload: The member selection dot . operator.
This means C++ has the ability to provide the operators with a special meaning for a data type, this ability is known as operator overloading. For example, we can overload an operator '+' in a class like String so that we can concatenate two strings by just using +.
The operator overloading defines a type conversion operator that can be used to produce an int type from a Counter object. This operator will be used whenever an implicit or explict conversion of a Counter object to an int is required. Notice that constructors also play a role in type conversion.
template<class T> struct is_wrap : std::false_type {};
template<class T> struct is_wrap<Wrap<T>> : std::true_type {};
template<class T1, class T2> typename std::enable_if<is_wrap<typename std::common_type<T1, T2>::type>::value, bool>::type operator == (const T1& t1, const T2& t2)
{
const typename std::common_type<T1, T2>::type& tc1 = t1, tc2 = t2;
// compare with tc1 and tc2
}
Someone else will articulate this better, but I think the problem is that the compiler can't deduce T
in Wrap<T>
without you passing it a Wrap
object. I think your situation should be resolved if you explicitly give the operator==
a template argument: operator==<int>(7, 4)
, for example should work.
I don't have a compiler in front of me, but here's my try:
template<typename T>
typename std::enable_if<std::is_convertible<Wrap<T>, T>::value, bool>::type operator==(const Wrap<T>& l, const T& r)
{
return l.stuff == Wrap<T>(r).stuff;
}
template<typename T>
typename std::enable_if<std::is_convertible<Wrap<T>, T>::value, bool>::type operator==(const T& l, const Wrap<T>& r)
{
return r == l; // call above operator
}
This should work if either side is a Wrap
and the other side isn't. You could also do both sides as const T&
, however if Wrap
is really implicitly constructible from any T
you will wind up using your operator==
for many unintended comparisons, even of int
s, string
s, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With