枚举类和全局运算符〜重载

时间:2014-04-16 11:49:49

标签: c++11

请考虑以下代码:

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; }

这是有效的C ++ 11吗?

Clang接受了。 Gcc给出了一个错误:

 % 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>();

代码从gcc错误报告中减少:     http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60852

这是未减少的测试用例:

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

enum class E {};

int main()
{ std::cout << boost::has_complement<E>() << std::endl; }

1 个答案:

答案 0 :(得分:8)

GCC就在这里,范围枚举,又名enum class不会隐式转换为int或其他任何东西。通过扩展,它们没有内置operator~,因此您需要明确转换:

#include <iostream>
#include <type_traits>

enum class E { val };

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

删除struct D和全局operator~后,clang会给出错误提示。这是一个明显的错误,因为operator~(D)首先不是候选人:

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

关于收集过载的规则§13.3.1.2:

  

对于具有cv不合格类型的操作数的一元运算符@   版本是T1,[...],指定了三组候选函数   会员候选人,非会员       候选人和内置候选人的构建如下:

结束:

  

但是,如果没有操作数具有类类型,则只有那些非成员   查找集中具有T1或类型的第一个参数的函数   当T1是枚举时,引用(可能是cv-qualified)T1“   类型,[...],是候选函数。

总而言之,因为E是非类型的,所以只考虑使用E或E引用的自由函数运算符。