是否允许使用具有相同整数值的枚举专门化模板?

gez*_*eza 16 c++ language-lawyer c++17

看看这个简单的片段:

enum class Enum1 { Value };
enum class Enum2 { Value };
template <auto> struct Foo;
template <> struct Foo<Enum1::Value> { };
template <> struct Foo<Enum2::Value> { };
Run Code Online (Sandbox Code Playgroud)

Clang编译了这个,但是gcc-7.2失败了:

x.cpp:5:20:错误:重新定义'struct Foo <(Enum1)0>'template <> struct Foo {};

此错误消息似乎无效,如第5行所示Enum2::Value.

哪个编译器正确?这是符合规范的代码吗?

Vit*_*meo 15

[dcl.type.auto.deduct]中:

A型T包含占位符类型,和相应的初始值设定e,被确定如下:

  • 对于使用包含占位符类型的类型T声明的非类型模板参数,是非类型模板参数的声明类型,并且e是相应的模板参数.

这似乎表明推导出的类型将是decltype(Enum1::Value),并且值将是Enum1::Value.


decltype(Enum1::Value)等于decltype(Enum2::Value)?这段代码......

static_assert(std::is_same_v<decltype(Enum1::Value), decltype(Enum2::Value)>);
Run Code Online (Sandbox Code Playgroud)

...无法使用clang ++ 6g ++ 8进行编译.


可能已经暴露了gcc中的一个bug.正如Johannes Schaub在评论中指出的那样,还有一段支持gcc的行为.

有一个错误报告打开:#79092.


另请注意,两个编译器都接受以下代码:

template <typename T, T> struct Foo;
template <> struct Foo<decltype(Enum1::Value), Enum1::Value> { };
template <> struct Foo<decltype(Enum2::Value), Enum2::Value> { };
Run Code Online (Sandbox Code Playgroud)

template <auto> 表现不同于(恕我直言)令人惊讶和不受欢迎.

  • 那么,标准也说[this](http://eel.is/c++draft/temp#arg.nontype-2).*"模板参数类型的转换常量表达式"*.这表明**应该被考虑在内.我认为Clang和GCC在这里都不会有错.这可能需要一份缺陷报告.它应该是清楚的. (5认同)
  • 本段似乎表明GCC在比较显式专业化的模板ID时不包括非类型模板参数的类型是正确的:http://eel.is/c++draft/temp.type(BTW通过尝试`Foo <0>`vs`Foo <0L>`,可以更容易地揭示差异. (3认同)
  • 对于它的价值,[clang和gcc似乎不同意它们是否相同](https://godbolt.org/g/YVTN4x),在更简单的情况下 (3认同)