Why does this not work, since there is an option to 'construct' implicitly?
class A {};
template<typename T>
class Type {
public:
Type() = default;
Type(T* ptr) {
}
};
template<typename T>
bool operator==(Type<T> l, Type<T> r) {
return true;
}
int main() {
A a;
Type<A> type(&a);
bool v = (type == &a); // Does not work
//bool v = (type == Type<A>(&a)); // That would work
}
Why is the implicit construct Type<A>
with (&base
, which is A*
) not used?
How could I write this code to make it work?
User-defined conversions are not considered when a function template is checked for viability.
When checking a function template for viability, the implementation tries to deduce template parameters according to template parameter deduction rules. These rules do not involve any type conversions (only type adjustments like removal of qualifiers and references). If deduction fails, the candidate is rejected.
In your case, T
cannot be deduced from Type<A>
and A
. You need both arguments to have the same type Type<X>
for the deduction to succeed.
You could make the operator overload a friend function inside your class Type
as such:
template<typename T>
class Type {
public:
Type() = default;
Type(T* ptr) {
}
inline friend bool operator==(Type<T> l, Type<T> r) {
return true;
}
};
This ensures the operator is actually instantiated from the moment you declare the variable Type<A> type;
.
In your case it's not instantiated. The compiler could create an instance of the template when you call the operator, but it fails because the template operator declaration can't deduce the arguments Type<A>
and A*
. This is actually the error message you get:
error: no match for 'operator==' (operand types are 'Type' and 'A*')
As such the implicit construction of Type<A>
is not even considered because there's no function with the signature bool operator==(Type<A> l, Type<A> r)
that exists at this point.
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