George
George

Reputation: 25

Overloading operator on member enum of class template

I'd like to make a template overload of operator | for an enum inside a class template.

Here is a minimal example:

#include <iostream>
using namespace std;

template <class T>
struct test1 {
    enum test2 {
        test3, test4
    };
};

template <class T>
typename test1<T>::test2 operator | (typename test1<T>::test2 f1, typename test1<T>::test2 f2) {
    return static_cast<typename test1<T>::test2>(
        static_cast<unsigned>(f1) | static_cast<unsigned>(f2)
    );
}

int main() {
    test1<int>::test2 flags = test1<int>::test3 | test1<int>::test4; // error here
}

Live example.

Compiler shows the following diagnostic in this code:

In function 'int main()':
error: invalid conversion from 'int' to 'test1<int>::test2' [-fpermissive]
  test1<int>::test2 flags = test1<int>::test3 | test1<int>::test4;

I also tried compiling this code with LLVM 6.1.0.

What is the problem with this code?

Upvotes: 0

Views: 339

Answers (1)

Oktalist
Oktalist

Reputation: 14714

The problem is that in typename test1<T>::test2, template parameter T is in a non-deduced context, so C++ can not deduce its template argument from the types of the function arguments.

You can see this by explicitly instantiating the function template:

test1<int>::test2 flags = operator | <int> (test1<int>::test3, test1<int>::test4);

DEMO

Or by using a non-template friend function of the class template:

template <class T>
struct test1 {
    enum test2 {
        test3, test4
    };
    friend test2 operator | (test2 f1, test2 f2) {
        return static_cast<test2>(
            static_cast<unsigned>(f1) | static_cast<unsigned>(f2)
        );
    }
};

int main() {
    test1<int>::test2 flags = test1<int>::test3 | test1<int>::test4;
}

DEMO

See also:

Upvotes: 2

Related Questions