无法将多个初始化程序列表传递给可变参数函数模板

fre*_*low 10 c++ templates initializer-list variadic-templates c++11

尝试传递可变数量的初始化列表时,我不明白错误消息:

template<typename... Values>
void foo(Values...)
{
}

int main()
{
    foo(1, 2, 3, "hello", 'a');   // OK

    foo({1}, {2, 3});             // ERROR
}
Run Code Online (Sandbox Code Playgroud)

错误消息抱怨参数太多:

prog.cpp: In function ‘int main()’:
prog.cpp:9:20: error: too many arguments to function
                      ‘void foo(Values ...) [with Values = {}]’
     foo({1}, {2, 3});
                    ^
prog.cpp:2:6: note: declared here
 void foo(Values...)
      ^
Run Code Online (Sandbox Code Playgroud)

但是,我是否应该无法传递尽可能多的参数?[ 意见链接 ]

seh*_*ehe 11

问题可能是可导性.{}可以是任何参数的统一初始化器.

这有效:

#include <initializer_list>

template<typename... Values>
void foo(std::initializer_list<Values>... args)
{
}

template<typename... Values>
void foo(Values&&... args)
{
}

int main()
{    
    foo(1, 2, 3, "hello", 'a');
    foo({1}, {2, 3});
}
Run Code Online (Sandbox Code Playgroud)

在科利鲁看到它

  • 确实; `template <class T> void foo(T);`不能从参数`foo({1,2})推断;`(参数`T`变成非推导的上下文),但有一些特殊的规则允许推导出`template <class T> void foo(std :: initializer_list <T>);`(以及相同的参数). (3认同)
  • 这个参考文献显示了几乎这个问题的一个例子http://en.cppreference.com/w/cpp/language/function_template#Template_argument_deduction (2认同)

Dav*_*e S 7

问题不在于varadic参数,而是编译器不能推断括号括起初始化列表的类型,除非你声明参数的情况 std::initializer_list<T>

§14.8.2.1模板参数推导是通过将每个函数模板参数类型(称之为P)与调用的相应参数的类型(称之为A)进行比较来完成的,如下所述.如果从P中删除引用和cv限定符,则为某些P0提供std :: initializer_list,并且该参数是初始化列表(8.5.4),则对初始化列表的每个元素执行推导,将P0作为函数模板参数type和initializer元素作为其参数.否则,初始化列表参数 会将参数视为非推导上下文(14.8.2.5).

下面还有一个例子

template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for T
Run Code Online (Sandbox Code Playgroud)