我有以下代码:
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时类型推导的方式有关。如果这符合标准,那么一些参考就会很好。
答案 0 :(得分:1)
std::make_shared
从函数调用的参数中推导出第二个模板参数。 braced-init-list不是表达式,因此没有类型。因此模板参数推导不能从中推导出类型。
来自§14.8.2.5/ 5 [temp.deduct.type]
但是,未推断的背景是:
-...
- 一个函数参数,其关联参数是初始化列表(8.5.4),但该参数没有std::initializer_list
或者可能是cv-qualifiedstd::initializer_list
类型的引用。 [示例:template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T
- 示例]
auto
是一个特殊情况,允许从braced-init-list中推导出std::initializer_list<T>
。
§7.1.6.4/ 7 [dcl.spec.auto]
...
否则,通过使用新发明的类型模板参数U或更换P
的出现次数,从T
获取auto
如果初始化程序是 braced-init-list ,则std::initializer_list<U>
。使用函数调用中的模板参数推导规则1>(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
- 示例]
在您的示例中,变量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});