MathQues
MathQues

Reputation: 129

Why I get the following error: "no match for 'operator=='" ? (nested class with template)

Given the following code:

template<class T>
class TemplateClass {
    T val;
public:
    TemplateClass(T val) :
            val(val) {
    }
    TemplateClass(const TemplateClass& tc) = default;
    TemplateClass& operator=(const TemplateClass& tc) = default;

    class Ele {
        T x;
    public:
        Ele(T x) :
                x(x) {
        }
        template<class S>
        friend bool operator==(const typename TemplateClass<S>::Ele& e1,
                const typename TemplateClass<S>::Ele& e2);
    };
};

template<class T>
bool operator==(const typename TemplateClass<T>::Ele& e1,
        const typename TemplateClass<T>::Ele& e2) {
    return e1.x == e2.x;
}

int main() {
    TemplateClass<int>::Ele e1(4);
    TemplateClass<int>::Ele e2(3);
    if (e1 == e2) {  // *********** error
        std::cout << "ok" << std::endl;
    }
}  

I get the following error:

no match for 'operator==' (operand types are 'TemplateClass<int>::Ele' and 'TemplateClass<int>::Ele')

Can someone tell me how can I fix it and what is the problem?

Upvotes: 2

Views: 432

Answers (2)

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136485

In addition to the answers here, you can use friend injection technique to fix the error:

template<class T>
class TemplateClass {
    // ...
    class Ele {
        // ...
        friend bool operator==(const Ele& e1, const Ele& e2) {
            return e1.x == e2.x;
        }
    };
};

Note that you do not need problematic typename TemplateClass<S>::Ele here at all.

Upvotes: 1

songyuanyao
songyuanyao

Reputation: 172994

Nested name of a type belongs to non-deduced contexts:

1) The nested-name-specifier (everything to the left of the scope resolution operator ::) of a type that was specified using a qualified-id:

So operator== fails to be invoked because template argument deduction fails; template parameter can't be deduced.

You might make it a non-template function, and define it inside the class definition. e.g.

template<class T>
class TemplateClass {
    ...
    class Ele {
        ...
        friend bool operator==(const typename TemplateClass<T>::Ele& e1,
                               const typename TemplateClass<T>::Ele& e2) {
            return e1.x == e2.x;
        }
    };
};

LIVE

Or make it non-template member function, then you might define them out of the class definition. e.g.

template<class T>
class TemplateClass {
    ...
    class Ele {
        ...
        bool operator==(const typename TemplateClass<T>::Ele& e2) const;
        bool operator!=(const typename TemplateClass<T>::Ele& e2) const;
    };
};

template<class T>
bool TemplateClass<T>::Ele::operator==(const typename TemplateClass<T>::Ele& e2) const {
    return x == e2.x;
}
template<class T>
bool TemplateClass<T>::Ele::operator!=(const typename TemplateClass<T>::Ele& e2) const {
    return ! (*this == e2);
}

LIVE

Upvotes: 2

Related Questions