web-dev-qa-db-ja.com

テンプレート控除ガイドとは何ですか?いつ使用する必要がありますか?

C++ 17標準では、「テンプレート推論ガイド」が導入されています。これらは、このバージョンの標準で導入されたコンストラクターの新しいテンプレート引数控除と関係があると思いますが、それらが何であり、何のためにあるのかについての簡単なFAQスタイルの説明はまだ見ていません。

  • C++ 17のテンプレート推論ガイドとは何ですか?

  • なぜ(そしていつ)必要なのですか?

  • それらを宣言するにはどうすればよいですか?

76
Tristan Brindle

テンプレート推論ガイドは、一連のパラメーター(およびそのタイプ)をテンプレート引数に変換する方法をコンパイラーに指示する、テンプレートクラスに関連付けられたパターンです。

最も単純な例は、std::vectorと、イテレーターのペアをとるコンストラクターの例です。

template<typename Iterator>
void func(Iterator first, Iterator last)
{
  vector v(first, last);
}

コンパイラは、vector<T>T型が何であるかを把握する必要があります。答えは何ですか? Ttypename std::iterator_traits<Iterator>::value_typeでなければなりません。しかし、コンパイラにwithoutを入力する必要があるのはどうすればvector<typename std::iterator_traits<Iterator>::value_type>と入力するのでしょうか?

控除ガイドを使用します:

template<typename Iterator> vector(Iterator b, Iterator e) -> 
    vector<typename std::iterator_traits<Iterator>::value_type>;

これは、そのパターンに一致するvectorコンストラクターを呼び出すと、->の右側のコードを使用してvector特殊化を推定することをコンパイラーに伝えます。

引数からの型の推定がそれらの引数のいずれかの型に基づいていない場合、ガイドが必要です。 initializer_listからvectorを初期化するには、vectorTを明示的に使用するため、ガイドは不要です。

左側は必ずしもコンストラクターを指定するわけではありません。それが機能する方法は、型でテンプレートコンストラクター推論を使用する場合、すべての推論ガイドに対して渡す引数と一致することです(プライマリテンプレートの実際のコンストラクターは暗黙のガイドを提供します)。一致する場合、それを使用して、どのテンプレート引数をタイプに提供するかを決定します。

しかし、いったんその推論が行われると、コンパイラーがその型のテンプレートパラメーターを計算すると、その型のオブジェクトの初期化は、あたかも何も起こらなかったかのように進行します。つまり、選択した控除ガイドは、constructor選択と一致する必要はありません。

また、これは、集計および集計の初期化でガイドを使用できることを意味します。

template<typename T>
struct Thingy
{
  T t;
};

Thingy(const char *) -> Thingy<std::string>;

Thingy thing{"A String"}; //thing.t is a `std::string`.

したがって、推論ガイドは、初期化されている型を把握するためにのみ使用されます。初期化の実際のプロセスは、その決定が行われると、以前とまったく同じように機能します。

88
Nicol Bolas