初始化列表中的对象初始化问题

时间:2014-08-07 09:53:43

标签: c++ c++11 initializer-list list-initialization

我有以下代码:

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

1 个答案:

答案 0 :(得分:1)

std::make_shared从函数调用的参数中推导出第二个模板参数。 braced-init-list不是表达式,因此没有类型。因此模板参数推导不能从中推导出类型。

来自§14.8.2.5/ 5 [temp.deduct.type]

  

未推断的背景是:
   - ...
   - 一个函数参数,其关联参数是初始化列表(8.5.4),但该参数没有std::initializer_list或者可能是cv-qualified std::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>。使用函数调用中的模板参数推导规则(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});