std::make_shared
从函数调用的参数推导出它的第二个模板参数。大括号初始化列表不是表达式,因此没有类型。因此模板参数推导不能从中推导出类型。
从§14.8.2.5/5 [temp.deduct.type]
非推导上下文是:
— ...
— 一个函数参数,其关联参数是一个初始化列表 (8.5.4),但该参数没有std::initializer_list
或不引用可能的 cv 限定std::initializer_list
类型。[示例:
template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for T
—结束示例]
auto
然而,是一种特殊情况,可以std::initializer_list<T>
从花括号初始化列表中推导出来。
§7.1.6.4/7 [dcl.spec.auto]
...
否则,P
通过T
将出现的 替换为auto
新发明的类型模板参数 U 或者,如果初始值设定项是一个花括号初始化列表,则使用std::initializer_list<U>
. U
从函数调用(14.8.2.1)中使用模板实参推导规则推导出一个值P
,其中是函数模板形参类型,初始值设定项是对应的实参。如果扣除失败,则声明格式错误。否则,为变量或返回类型推导的类型是通过将推导的代U
入来获得的P
。[示例:
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type
—结束示例]
在您的示例中,变量list
的类型为initializer_list<shared_ptr<int>>
,当您将其传递给 时make_shared
,vector
可以从中构造 a ,然后将其用于直接初始化A
实例。
其他选择是构建一个vector
auto res = std::make_shared<A>(std::vector<std::shared_ptr<int>>{x, y});
构造 an A
,然后将其移动
auto res = std::make_shared<A>(A{{x, y}});
make_shared
或明确指定模板参数
auto res = std::make_shared<A, std::initializer_list<std::shared_ptr<int>>>({x, y});