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


87

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

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

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

  • どうすれば宣言できますか?



特に、控除ガイドが実際にC ++ 17 STLによって提供されているかどうかを知りたいと思います(たとえば、std :: pairまたはstd :: tuple)。C ++ 17の時点での「控除可能な」標準テンプレートタイプの完全なリストは何ですか?
Quuxplusone 2017


コンパイラがこれをサポートしているかどうか知りたいです。gcc、clang、vc ++を試しました。rextester.com/DHPHC32332ネヴァーマインドは、私はそれが8.1 C ++ 17と2A G ++ -std = C ++ 17 -O2 -Wall -pedantic -pthread main.cppに&& ./a.out ++ GCでのみ動作見出さ
ジャン・シモンBrochu19年

回答:


98

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

最も単純な例は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つの型に基づいていない場合は、ガイドが必要です。vectorfromを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`.

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


7
うーん、ガイドがあってもvector v{first, last};正しいことをしないことに気づきました:(
TC

3
@ TC…正しいことがイテレータのベクトルを作成することでない限り。そしてstd::string{32,'*'}[0] == ' '(ASCIIの場合)。しかし、これはC ++ 11以降すべて当てはまります。
Arne Vogel

2
アロケータベクトルパラメータはどうなりますか?アロケータベクトルパラメータにデフォルトの引数がない場合はどうなりますか?(InputIteratorから推測することはできません)
gnzlbg 2017年

@NicolBolas:部分的または完全に特殊化されたクラス(コンストラクターがプライマリテンプレートのパラメータータイプと一致する必要がないことは明らかです)のコンテキストで、暗黙的および明示的な演繹ガイドがどのように機能するかについて詳しく説明していただけませんか?クイック検索でこれに関する情報を見つけるのは難しいです。
user541686 2018

1
@NicolBolas:なるほど。質問が明示的な演繹ガイドに関するものであるかどうかは私にはわかりません...このコメントに文字通り書いたものを含めるだけで役立つと思います。
user541686 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.