从初始化列表初始化对象时出现问题



我有以下代码:

    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从函数调用的实参中推导出其第二个模板形参。大括号初始化列表不是表达式,因此没有类型。因此,模板实参演绎不能从中演绎出类型。

从<<p> em>§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

-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});

最新更新