我有以下代码:
class A {
public:
A(std::vector<std::shared_ptr<int>>){}
};
auto x = std::make_shared<int>(0);
auto y = std::make_shared<int>(1);
auto list = {x, y};
auto res = std::make_shared<A>({x, y});
在这个例子中,如果我传递给res变量列表,它会编译,否则就像直接使用初始化列表一样,它会失败http://ideone.com/8jYsDY
我猜这与涉及initializer_list时类型演绎的工作方式有关。如果这是标准的一致性,一些参考将是好的。
std::make_shared
从函数调用的实参中推导出其第二个模板形参。大括号初始化列表不是表达式,因此没有类型。因此,模板实参演绎不能从中演绎出类型。
然而,未推断的上下文为:
,-...
,—一个函数形参,其关联的实参是一个初始化列表(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
-end example]
auto
是一种特殊情况,允许从带括号的init-list中推断出std::initializer_list<T>
。
§7.1.6.4/7 [dcl.spec.auto]
...
否则,通过将出现的auto
替换为新创建的类型模板形参U,或者,如果初始化式是带括号的初始化列表,则将std::initializer_list<U>
替换为,从T
获得P
。使用从函数调用(14.8.2.1)中推导模板实参的规则推导U
的值,其中P
是函数模板形参类型,初始化式是相应的实参。如果演绎失败,则声明格式错误。否则,通过将推导出的U
替换为P
来获得变量的类型或返回类型。(例子:auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> auto x2 = { 1, 2.0 }; // error: cannot deduce element type
-end example]
在您的示例中,变量list
具有initializer_list<shared_ptr<int>>
类型,当您将其传递给make_shared
时,可以从它构造vector
,然后使用它直接初始化A
实例。
其他选项是构造一个vector
auto res = std::make_shared<A>(std::vector<std::shared_ptr<int>>{x, y});
构造一个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});