Consider the following code:
enum A : unsigned { a = 1, b = 2, c = 4 };
class B
{
friend constexpr A operator|(A a1, A a2)
{ return A(unsigned(a1) | unsigned(a2)); }
};
template <A a>
class C
{
};
int main()
{
C<a|c> c;
}
When compiled with g++ (4.8.1, -std=c++1), I get the following error:
test.C: In function ‘int main()’:
test.C:16:12: error: invalid conversion from ‘unsigned int’ to ‘A’ [-fpermissive]
C<a|c> c;
Which tells me that the operator is not being found. However, if the code is changed to:
enum A : unsigned { a = 1, b = 2, c = 4 };
constexpr A operator|(A a1, A a2)
{ return A(unsigned(a1) | unsigned(a2)); }
template <A a>
class C
{
};
int main()
{
C<a|c> c;
}
Then it compiles and runs fine. Is the error in the first case a compiler error, or I do misunderstand something? I would like to use the method of Boost.Operators to easily define operators by declaring a class with base classes from templates which define the operators, but this result precludes that in this case.
Thanks for any help.
argument-dependent lookup (ADL) These function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup. Argument-dependent lookup makes it possible to use operators defined in a different namespace.
In the C++ programming language, argument-dependent lookup (ADL), or argument-dependent name lookup, applies to the lookup of an unqualified function name depending on the types of the arguments given to the function call.
Another way to solve it (other than jogojapan already mentioned), is to simply declare the friend function outside the scope.
enum A : unsigned { a = 1, b = 2, c = 4 };
//declaration
constexpr A operator|(A a1, A a2);
class B
{
//definition inside, ok.
friend constexpr A operator|(A a1, A a2)
{ return A(unsigned(a1) | unsigned(a2)); }
};
template <A a>
class C
{
};
int main()
{
C<a|c> c;
}
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