1

我有以下代码:

    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 时类型推导的工作方式有关。如果这是符合标准的,那么一些参考会很好。

4

1 回答 1

1

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_sharedvector可以从中构造 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});
于 2014-08-07T14:09:48.670 回答