g++ 和 clang++ 不同的行为推导可变参数模板“auto”值
g++ and clang++ different behaviour deducing variadic template `auto` values
另一个"who's right between g++ and 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++
}
clang++(8.0.0,例如)编译和 link 没有问题,其中 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...
不同 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}'
-- 编辑 2 --
camp0 观察到(感谢)g++ 编译这段代码直到版本 7.4。
从 8.1 引入的错误或我的代码存在错误并且 g++ 已从 8.1 更正他的代码?
None三个编译器正确
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 and a GCC bug report。
另一个"who's right between g++ and 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++
}
clang++(8.0.0,例如)编译和 link 没有问题,其中 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...
不同 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}'
-- 编辑 2 --
camp0 观察到(感谢)g++ 编译这段代码直到版本 7.4。
从 8.1 引入的错误或我的代码存在错误并且 g++ 已从 8.1 更正他的代码?
None三个编译器正确
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 and a GCC bug report。