C ++ 17標準では、「テンプレート演繹ガイド」が導入されています。これらは、このバージョンの標準で導入されたコンストラクターの新しいテンプレート引数の推論と関係があると思いますが、それらが何であり、何のためにあるのかについての簡単なFAQスタイルの説明はまだ見ていません。
C ++ 17のテンプレート控除ガイドとは何ですか?
なぜ(そしていつ)それらが必要なのですか?
どうすれば宣言できますか?
C ++ 17標準では、「テンプレート演繹ガイド」が導入されています。これらは、このバージョンの標準で導入されたコンストラクターの新しいテンプレート引数の推論と関係があると思いますが、それらが何であり、何のためにあるのかについての簡単なFAQスタイルの説明はまだ見ていません。
C ++ 17のテンプレート控除ガイドとは何ですか?
なぜ(そしていつ)それらが必要なのですか?
どうすれば宣言できますか?
回答:
テンプレート推論ガイドは、テンプレートクラスに関連付けられたパターンであり、コンストラクター引数(およびそのタイプ)のセットをクラスのテンプレートパラメーターに変換する方法をコンパイラーに指示します。
最も単純な例はstd::vector
、イテレータペアをとるのとそのコンストラクタです。
template<typename Iterator>
void func(Iterator first, Iterator last)
{
vector v(first, last);
}
コンパイラは、vector<T>
のT
型がどうなるかを理解する必要があります。私たちは答えが何であるかを知っています。T
である必要がありますtypename std::iterator_traits<Iterator>::value_type
。しかし、入力せずにコンパイラーにどのように伝えるの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
の右側のコードを使用して特殊化を推測することをコンパイラーに通知します->
。
引数からの型の推定がそれらの引数の1つの型に基づいていない場合は、ガイドが必要です。vector
fromをinitializer_list
明示的に初期化するには、vector
'sを使用するT
ため、ガイドは必要ありません。
左側は必ずしも実際のコンストラクターを指定しているわけではありません。それが機能する方法は、型でテンプレートコンストラクター控除を使用する場合、すべての控除ガイドに対して渡す引数と一致することです(プライマリテンプレートの実際のコンストラクターは暗黙のガイドを提供します)。一致するものがある場合は、それを使用して、型に提供するテンプレート引数を決定します。
しかし、その推論が行われると、コンパイラが型のテンプレートパラメータを把握すると、その型のオブジェクトの初期化は、何も起こらなかったかのように進行します。つまり、選択した控除ガイドは、選択したコンストラクターと一致する必要はありません。
これは、アグリゲートとアグリゲートの初期化でガイドを使用できることも意味します。
template<typename T>
struct Thingy
{
T t;
};
Thingy(const char *) -> Thingy<std::string>;
Thingy thing{"A String"}; //thing.t is a `std::string`.
したがって、演繹ガイドは、初期化される型を理解するためにのみ使用されます。初期化の実際のプロセスは、その決定が行われると、以前とまったく同じように機能します。
vector v{first, last};
正しいことをしないことに気づきました:(
std::string{32,'*'}[0] == ' '
(ASCIIの場合)。しかし、これはC ++ 11以降すべて当てはまります。