Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write operator== to work with implicitly casted/constructed types

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?

like image 240
user2561762 Avatar asked Feb 09 '18 10:02

user2561762


2 Answers

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.

like image 178
n. 1.8e9-where's-my-share m. Avatar answered Oct 18 '22 10:10

n. 1.8e9-where's-my-share m.


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.

like image 45
JBL Avatar answered Oct 18 '22 10:10

JBL