Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should a friend operator in a class with enum parameters be found by Koenig lookup?

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.

like image 959
BryFry Avatar asked Jan 26 '14 01:01

BryFry


People also ask

What is argument-dependent lookup why it is useful?

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.

How does ADL work C++?

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.


1 Answers

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;
}
like image 94
user534498 Avatar answered Oct 06 '22 11:10

user534498