Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

enum class and global operator~ overloading

Tags:

c++11

Consider the following code:

struct D
{
  template <class T> D (T);
};
int operator~(const D &);

template <typename T> T &make ();

template <typename Rhs> struct H
{
  static const int value = sizeof ~make<Rhs>();
};

enum class E;

int main () { return H<E>::value; }

Is this valid C++11?

Clang accepts it. Gcc gives an error:

 % gcc -std=c++11 b.ii
b.ii: In instantiation of ‘const int H<E>::value’:
b.ii:16:28:   required from here
b.ii:11:35: error: no match for ‘operator~’ (operand type is ‘E’)
   static const int value = sizeof ~make<Rhs>();

The code was reduced from a gcc bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60852

This is the unreduced test case:

#include <boost/type_traits.hpp>
#include <iostream>

enum class E {};

int main()
{ std::cout << boost::has_complement<E>() << std::endl; }
like image 698
octoploid Avatar asked Apr 16 '14 11:04

octoploid


1 Answers

GCC is right here, scoped enumeration, aka enum class are not implicitly converting to int or anything else. By extension, they do not have a built-in operator~, so you need to cast explicitly :

#include <iostream>
#include <type_traits>

enum class E { val };

int main () { 
    std::cout << ~std::underlying_type<E>::type(E::val);
} 

By removing your struct D and the global operator~, clang give the good error. It is a bug clearly as operator~(D) is not a candidate in the first place :

main.cpp:17:35: error: invalid argument type 'E' to unary expression
static const int value = sizeof ~make<Rhs>();

The rules about collecting the overloads § 13.3.1.2 :

For a unary operator @ with an operand of a type whose cv-unqualified version is T1, [...], three sets of candidate functions, designated member candidates, nonmember candidates and built-in candidates, are constructed as follows:

And the finish :

However, if no operand has a class type, only those non-member functions in the lookup set that have a first parameter of type T1 or reference to (possibly cv-qualified) T1”, when T1 is an enumeration type, [...], are candidate functions.

To summarize, because E is of non class type, only free function operators taking a E or a reference to E are considered.

like image 159
galop1n Avatar answered Nov 14 '22 11:11

galop1n