mar*_*trz 4 c++ variadic-functions variadic-templates c++11
我创建了一个工厂功能模板:
template <typename M, typename... Args>
std::shared_ptr<M> create(Args... args)
{
return std::make_shared<M>(args...);
}
Run Code Online (Sandbox Code Playgroud)
还有一个简单的容器:
struct Group {
std::vector<int> vec;
Group(std::initializer_list<int> il) : vec(il) {}
};
Run Code Online (Sandbox Code Playgroud)
然后我尝试创建一个组
int main()
{
auto gr = create<Group>({1, 2, 3});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这不会编译,
error: no matching function for call to 'create'
auto gr = create<Group>({1, 2, 3});
candidate function not viable: requires 0 arguments, but 1 was provided
std::shared_ptr<M> create(Args... args)
^
Run Code Online (Sandbox Code Playgroud)
但是如果我使用一个临时变量:
int main(int argc, char *argv[])
{
std::initializer_list<int> il = {1, 2, 3};
auto gr = create<Group>(il);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是的。为什么?
对于这种情况,推荐的解决方案是什么?
模板参数不能从初始值设定项列表(它是非推断上下文)中推导,而可以从type表达式中推导std::initializer_list<something>。两者不一样。
[temp.deduct.call] / 1模板参数推导是通过将每个函数模板参数类型(称为
P)与调用的相应参数类型(称为A)进行比较,如下所述。如果删除的引用和cv修饰符从P给出std::initializer_list<P'>一些P'和参数为初始化值列表(8.5.4),然后进行扣除,而不是用于初始化列表中的每个元素,以P'作为函数模板参数类型和初始值设定元素作为其论点。否则,使用初始化列表参数将参数视为非推论上下文(14.8.2.5)。[ 示例:Run Code Online (Sandbox Code Playgroud)template<class T> void f(std::initializer_list<T>); f({1,2,3}); // T deduced to int f({1,"asdf"}); // error: T deduced to both int and const char* template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T—结束示例 ]