c++ - g++ 和 clang++ 推导可变参数模板 `auto` 值的不同行为

标签 c++ language-lawyer c++17 variadic-templates template-argument-deduction

另一个“g++ 和 clang++ 之间谁是正确的?”

这次我确信这是一个 g++ bug,但我请求标准专家的确认。

给出以下代码

template <template <auto...> class Cnt,
          typename ... Types,
          Types ... Vals>
void foo (Cnt<Vals...>)
 { }

template <auto ...>
struct bar
 { };

int main ()
 {
   foo(bar<0, 1>{});  // compile both
   foo(bar<0, 1L>{}); // only clang++ compile; error from g++
 }

Live demo

clang++(8.0.0,例如)编译和链接没有问题,而 g++(9.2.0,例如)在编译第二个 foo() (但不是第一个)时给出以下错误调用

prog.cc: In function 'int main()':
prog.cc:16:20: error: no matching function for call to 'foo(bar<0, 1>)'
   16 |    foo(bar<0, 1L>{}); // only clang++ compile; error from g++
      |                    ^
prog.cc:6:6: note: candidate: 'template<template<auto ...<anonymous> > class Cnt, class ... Types, Types ...Vals> void foo(Cnt<Vals ...>)'
    6 | void foo (Cnt<Vals...>)
      |      ^~~
prog.cc:6:6: note:   template argument deduction/substitution failed:
prog.cc:16:20: note:   mismatched types 'int' and 'long int'
   16 |    foo(bar<0, 1L>{}); // only clang++ compile; error from g++
      |                    ^
prog.cc:16:20: note:   'bar<0, 1>' is not derived from 'Cnt<Vals ...>'

如果我理解正确的话,g++ 要求 Vals...Types... 与 clang++ 接受 Vals... 具有不同的类型...

谁是对的?

--编辑--

正如 Marek R 所指出的(感谢),MSVC (v19.22) 也无法编译。

但是,如果我理解正确的话,编译第一个 foo() 调用也会失败,并出现以下错误

<source>(13): error C2672: 'foo': no matching overloaded function found
<source>(13): error C2893: Failed to specialize function template 'void foo(Cnt<Vals...>)'
<source>(13): note: With the following template arguments:
<source>(13): note: 'Cnt=bar'
<source>(13): note: 'Types={}'
<source>(13): note: 'Vals={0, 1}'

-- 编辑 2--

camp0 观察到(感谢)g++ 编译此代码直到版本 7.4。

从 8.1 引入的错误或者是我的代码出现错误并且 g++ 已从 8.1 更正了他的代码?

最佳答案

三个编译器都不正确。

来自[temp.param]/17 :

If a template-parameter is a type-parameter with an ellipsis prior to its optional identifier or is a parameter-declaration that declares a pack ([dcl.fct]), then the template-parameter is a template parameter pack. A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded packs is a pack expansion. ... A template parameter pack that is a pack expansion shall not expand a template parameter pack declared in the same template-parameter-list. [ Example:

...

template <class... T, T... Values>              // error: Values expands template type parameter
  struct static_array;                          // pack T within the same template parameter list

— end example ]

因此,即使没有 foo(bar<0, 1L>{}); 行,代码也是格式错误的.

已经有一个 Clang bug report和海湾合作委员会bug report

关于c++ - g++ 和 clang++ 推导可变参数模板 `auto` 值的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57689726/

相关文章:

c++ - 如何使用仿函数创建 boost::packaged_task ?

c++ - #定义一个带索引的数组值

c++ - C++ 标准中短语 "constructors do not have names"的含义

c++ - 标准的意图是任何形式的 `nested-type-specifier followed by an identifier` 都可以称为合格 ID

c++ - 是否使用 std::move 转储成员可接受的设计?

c++ - 我的程序如何附加正在运行的程序?就像 gdb 一样。在 Linux 中

c++ - 为什么部分特化不需要前向声明?

c++ - 对 unordered_map 的奇怪行为感到震惊

c++ - 当参数转换为目标类型时,复制构造函数省略以直接初始化

c++ - 关于对齐存储和普通可复制/可破坏类型