请考虑以下代码:
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; }
Run Code Online (Sandbox Code Playgroud)
这是有效的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>();
Run Code Online (Sandbox Code Playgroud)
代码从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; }
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
通过删除你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>();
Run Code Online (Sandbox Code Playgroud)
关于收集过载的规则§13.3.1.2:
对于具有cv非限定版本为T1的类型的操作数的一元运算符@,[...],三组候选函数,指定成员候选者,非成员候选者和内置候选者,构造如下:
结束:
但是,如果没有操作数具有类类型,则只有查找集中具有类型T1的第一个参数或引用(可能是cv-qualified)T1"的非成员函数,当T1是枚举类型时,[.. .],是候选函数.
总而言之,因为E是非类型的,所以只考虑采用E或E的引用的自由函数运算符.