【问题标题】:Is it allowed to specialize a template with enums with the same integral value?是否允许使用具有相同整数值的枚举来专门化模板?
【发布时间】:2017-10-25 12:56:15
【问题描述】:

看看这个简单的sn-p:

enum class Enum1 { Value };
enum class Enum2 { Value };
template <auto> struct Foo;
template <> struct Foo<Enum1::Value> { };
template <> struct Foo<Enum2::Value> { };

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

x.cpp:5:20: 错误:重新定义‘struct Foo’模板 结构 Foo { };

此错误消息似乎无效,因为在第 5 行写入了Enum2::Value。

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

【问题讨论】:

    标签: c++ language-lawyer c++17


    【解决方案1】:

    在[dcl.type.auto.deduct]:

    包含占位符类型的类型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)>);
    

    ...无法同时使用 clang++ 6 和 g++ 8 进行编译。


    我认为你可能暴露了gcc中的一个错误。正如 Johannes Schaub 在 cmets 中指出的那样,还有一个 paragraph in favour of gcc's behavior。

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


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

    template <typename T, T> struct Foo;
    template <> struct Foo<decltype(Enum1::Value), Enum1::Value> { };
    template <> struct Foo<decltype(Enum2::Value), Enum2::Value> { };
    

    template &lt;auto&gt; 的行为与此不同会(恕我直言)令人惊讶和不受欢迎。

    【讨论】:

    • 这一段似乎表明 GCC 在比较显式特化的模板 ID 时不包括非类型模板参数的类型是正确的:eel.is/c++draft/temp.type(顺便说一句,区别可能更容易只需尝试 Foo&lt;0&gt; 与 Foo&lt;0L&gt; 即可暴露。
    • @JohannesSchaub-litb - 你指的是“它们对应的整数或枚举类型的非类型模板参数具有相同的值和”?它肯定适用于template&lt;Enum&gt; struct Foo 的情况,因为这两个值属于同一类型。但我认为在这种情况下并不太清楚并尝试。在0 vs 0L 案例中是否应该发生任何类型的衰减?
    • 为了它的价值,clang and gcc seems to disagree on whether they are the same,在更简单的情况下
    • 嗯,标准也说this。 “模板参数类型的转换常量表达式”。这表明类型应该被考虑在内。我认为 Clang 和 GCC 都不能在这里犯错。这可能需要缺陷报告。它应该是晶莹剔透的。
    • 我怀疑措辞有缺陷,因为[temp.param]/4 在涉及非类型参数时与[temp.type]/1 不同。
    猜你喜欢
    • 2011-05-31
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    • 2014-09-19
    相关资源
    最近更新 更多