【问题标题】:g++ and clang++ different behaviour with template specialization for auto argumentg++ 和 clang++ 不同的行为与自动参数的模板特化
【发布时间】:2019-08-21 13:22:28
【问题描述】:

使用 C++17 auto 模板参数我遇到了另一个 g++/clang++ 分歧。

给定以下简单代码

template <auto>
struct foo;

template <int I>
struct foo<I>
 { };

int main ()
 {
   foo<42l> f42; // <--- long constant, not int constant

   (void)f42; // avoid the "unused variable" warning
 }

我看到 clang++(例如 8.0.0)编译 g++(例如 9.2.0)给出以下错误的代码

prog.cc: In function 'int main()':
prog.cc:12:13: error: aggregate 'foo<42> f42' has incomplete type and cannot be defined
   12 |    foo<42l> f42;
      |             ^~~

如果我们使用int 常量而不是long 常量,两个编译器都会编译

  foo<42>  f42;  // compile with both clang++ and g++

所以我有两个关于 C++ 语言层的问题

(1) 它是合法的,在 C++17 中,特化一个模板,声明接收一个 auto 模板参数,用于特定类型的值(如我的代码中的 foo 特化)?

(2) 如果前面问题的答案是“是”,那么模板特化可以截取不同(但可转换)类型的值?

问题(2)差不多:是clang++还是g++?

【问题讨论】:

  • 如果添加 {} 会怎样 - 即。 template &lt;auto&gt; struct foo {}; ?
  • @SanderDeDycker - 也编译 g++。但这在我看来几乎是显而易见的(显然,第一个问题的答案是“是”):42l 案例被通用 foo&lt;auto&gt; 版本拦截。

标签: c++ language-lawyer c++17 template-specialization auto


【解决方案1】:

这是一个稍微不同的复制,它不依赖于不完整的类型:

template <auto> struct foo { static constexpr int value = 0; };
template <int I> struct foo<I> { static constexpr int value = 1; };

// ok on gcc, fires on clang which thinks foo<42L>::value is 1
static_assert(foo<42L>::value == 0);

这是一个clang错误。 42L 明显匹配 auto,毫无疑问。但它与int I 匹配吗?不,来自[temp.deduct.type]/19

如果P 有一个包含&lt;i&gt; 的表单,并且如果i 的类型不同于由封闭的simple-template-id 命名的模板的相应模板参数的类型em>,扣减失败。如果P有一个包含[i]的表格,并且i的类型不是整数类型,则推演失败。 [ 例子:

template<int i> class A { /* ... */ };
template<short s> void f(A<s>);
void k1() {
  A<1> a;
  f(a);             // error: deduction fails for conversion from int to short
  f<1>(a);          // OK
}


template<const short cs> class B { };
template<short s> void g(B<s>);
void k2() {
  B<1> b;
  g(b);             // OK: cv-qualifiers are ignored on template parameter types
}

结束示例 ]

为了查看42L 是否匹配特化,我们需要从42L推导出 int I,但失败了。因此,我们坚持主要专业。铿锵不会这样做。归档43076

【讨论】:

    猜你喜欢
    • 2013-12-14
    • 2018-07-15
    • 2018-10-16
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 2018-01-06
    • 1970-01-01
    • 2019-10-01
    相关资源
    最近更新 更多