5

コンテナーの基礎となるコンストラクターを呼び出すテンプレート コンストラクターを持つ std コンテナーから継承するクラスを考えてみましょう。このテンプレート コンストラクターは、単純なコピーおよび移動コンストラクターでは機能しますが、initializer_list ctor では機能しません。

template<typename container_T>
class test : public container_T {
public:
  using container_type = container_T;

  test() {} 

  // templated constructor
  template<typename T>
  test(T t)
    : container_T(t) {}

   // without this it won't compile
  test(std::initializer_list<typename container_T::value_type> l)
    : container_T(l) {}
};

int main() {    
  test<std::deque<int>> vdi1;
  test<std::deque<int>> vdi2({1,2,3,4,5,6,7,8,9});

  std::cout << "vdi2 before:" << std::endl;
  for(auto it : vdi2)
    std::cout << it << std::endl;

  test<std::deque<int>> vdi3(std::move(vdi2));

  std::cout << "vdi2 before:" << std::endl;
  for(auto it : vdi2)
    std::cout << it << std::endl;

  std::cout << "vdi3 before:" << std::endl;
  for(auto it : vdi3)
    std::cout << it << std::endl;

  return 0;
}

initializer_listコンストラクターを削除するvdi2と、コンパイルされません。私の質問: なぜ initializer_list はテンプレート コンストラクターによって推定されないのですか? そして、そうすることが可能ですか?

4

1 に答える 1

8

テンプレート化されたコンストラクターによって initializer_list が推定されないのはなぜですか?

その理由は{1,2,3,4,5,6,7,8,9}、型を持たないシンタティックな構造に過ぎないからです。したがって、コンパイラはTこの構文構造の型を推測できず、最初のコンストラクターは失敗します。

ただし、特別な標準規則std::initializer_list<T>(とりわけ) により、このシンタティック構造から を構築Tでき、 と推定できますint。したがって、2 番目のコンストラクターが機能します。

関数テンプレートの引数の型推論とは対照的に、

auto x = {1,2,3,4,5,6,7,8,9};

コンパイラは x の型を に設定しますstd::initializer_list<int>。そうでなければならないという特別なスタンダードルールもあります。厳密に言えば、これは型推論ではありません。前述のように、推論{1,2,3,4,5,6,7,8,9}される型がないからです。(ここで行われる型推定は だけですT = intstd::initializer_list<T>) ここで、コンパイラは の型を選択します (推定はしません) 。いずれにせよ、 の型がと推定されるという言葉の乱用を使用しても害はありません。xstd::initializer_list<int>xstd::initializer_list<int>

最後に、DyP がコメントで述べたように、おそらく必要なのは、基本コンテナー クラスからすべてのコンストラクター (1 つの引数を取るコンストラクターだけでなく) を継承することです。これを行うには、現在持っているすべてのコンストラクターを削除し、次の行だけを に追加しますtest

using container_type::container_type;
于 2013-10-21T10:34:19.030 に答える