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関数呼び出しの引数から 2 番目のテンプレート パラメーターを推定します。ブレース初期化リストは式ではないため、型はありません。したがって、テンプレート引数推定は、そこから型を推定できません。

§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

—終わりの例]

autostd::initializer_list<T>ただし、波括弧初期化リストから推測できる特殊なケースです。

§7.1.6.4/7 [dcl.spec.auto]

... PTautoそれ以外の場合は、 の出現箇所を新しく発明された型テンプレート パラメーター Uに置き換えるか、初期化子が波括弧初期化リストのstd::initializer_list<U>U場合はに置き換えることによってfromを取得ます。関数呼び出し(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_sharedavectorを構築できます。これは、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});
于 2014-08-07T14:09:48.670 に答える