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

max*_*x66 16 c++ language-lawyer variadic-templates template-argument-deduction c++17

另一个“谁在g ++和clang ++之间合适?”

这次,我确信这是一个g ++错误,但我要求标准专家进行确认。

给出以下代码

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++
 }
Run Code Online (Sandbox Code Playgroud)

现场演示

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 ...>'
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,那么g ++要求clang ++接受the are different Types...Vals...巧合。Vals...Types...

谁是对的?

-编辑-

正如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}'
Run Code Online (Sandbox Code Playgroud)

-编辑2-

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

是从8.1引入的错误,还是我的代码已被篡改,而g ++已从8.1中更正了他的代码?

xsk*_*xzr 10

这三个编译器都不正确。

[temp.param] / 17开始

如果template-parameter是在其可选标识符之前带有省略号的类型参数,或者是声明包的参数声明([dcl.fct]),则template-parameter是模板参数包。模板参数包是一个参数声明,其类型包含一个或多个未展开的包,即为包扩展。... 作为包扩展的模板参数包不应扩展在同一template-parameter-list中声明的模板参数包。[示例:

...

template <class... T, T... Values>              // error: Values expands template type parameter
  struct static_array;                          // pack T within the same template parameter list
Run Code Online (Sandbox Code Playgroud)

—结束示例]

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

已经有Clang 错误报告和GCC 错误报告

  • @ max66更新了答案。希望现在对您有所帮助。 (2认同)