空包的Functor可变参数模板包扩展在clang ++和g ++中给出了不同的结果

Con*_*tor 2 c++ templates language-lawyer variadic-templates c++14

以下代码使用clang ++ 3.8.0成功编译,无法使用g ++ 7.2.0(带-std=c++14 -O0 -Wall -Wextra -Werror -pedantic-errors编译标志)进行编译:

auto foo = [](auto functor, auto... argument_functors)
{
    functor(argument_functors()...);
};

auto do_nothing = [](auto...) {};


int main()
{
    foo(do_nothing);
}
Run Code Online (Sandbox Code Playgroud)

g ++错误消息:

main.cpp: In instantiation of '<lambda(auto:1, auto:2 ...)> [with auto:1 = <lambda(auto:3, ...)>; auto:2 = {}]':
main.cpp:11:16:   required from here
main.cpp:3:9: error: no match for call to '(<lambda(auto:3, ...)>) ()'
  functor(argument_functors()...);
  ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:6:29: note: candidate: template<class auto:3> <lambda(auto:3, ...)>::operator decltype (((const<lambda(auto:3, ...)>*)((const<lambda(auto:3, ...)>* const)0))->operator()(static_cast<auto:3&&>(<anonymous>))) (*)(auto:3, ...)() const <deleted>
 auto do_nothing = [](auto...) {};
                             ^
main.cpp:6:29: note:   template argument deduction/substitution failed:
main.cpp:3:9: note:   candidate expects 1 argument, 0 provided
  functor(argument_functors()...);
  ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:6:29: note: candidate: template<class auto:3> <lambda(auto:3, ...)>
 auto do_nothing = [](auto...) {};
                             ^
main.cpp:6:29: note:   template argument deduction/substitution failed:
main.cpp:3:9: note:   candidate expects 1 argument, 0 provided
  functor(argument_functors()...);
  ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

哪种编译器行为符合标准?

Bar*_*rry 6

这是gcc bug 64095.

来自[dcl.fct]/18:

当省略号出现在参数声明子句的末尾而没有前面的逗号时,存在语法歧义.在这种情况下,如果参数的类型命名一个尚未展开或包含的模板参数包,则省略号将被解析为abstract-declarator的一部分; 否则,它将被解析为parameter-declaration-clause的一部分.auto

基本上,(T...)在参数列表中可以解释为:

  • 一个未命名的类型参数T和省略号.
  • 一个函数参数包,包含模板参数包的类型T.

如果T是模板参数包auto,则假设消歧规则优先选择后者,但是gcc选择将其解释为省略号参数.