jtbandes:
次のテンプレート構造体を考えます:
template<typename T>
struct Foo {
Foo(T&&) {}
};
このコンパイルは、とT
なると推定されますint
。
auto f = Foo(2);
しかし、これはコンパイルされません。https://godbolt.org/z/hAA9TE
int x = 2;
auto f = Foo(x);
/*
<source>:12:15: error: no viable constructor or deduction guide for deduction of template arguments of 'Foo'
auto f = Foo(x);
^
<source>:7:5: note: candidate function [with T = int] not viable: no known conversion from 'int' to 'int &&' for 1st argument
Foo(T&&) {}
^
*/
しかし、Foo<int&>(x)
受け入れられています。
私は一見冗長なユーザ定義の控除ガイドを追加するときしかし、それは動作します:
template<typename T>
Foo(T&&) -> Foo<T>;
なぜことができないT
と推測されint&
、ユーザー定義の控除ガイドなし?
クルミ:
私は、転送の参照に関する合成された控除ガイドのための特定の例外があるので、ここで混乱が生じると思います。
それが真であることをコンストラクタから生成されたクラスのテンプレート引数控除を目的と正確にユーザー定義の控除ガイドを見てから発生した1と同じ、すなわち候補機能:
template<typename T>
auto f(T&&) -> Foo<T>;
しかし、コンストラクタから生成されたいずれかの、T&&
それがあるが、単純な右辺値の基準となる転送参照ユーザー定義の場合です。これによって指定される[temp.deduct.call] / 3(ドラフトN4659は、鉱山を強調する)C ++ 17標準の:
転送基準 CV-修飾されていないテンプレートパラメータに右辺値参照であるクラステンプレートのテンプレートパラメータを表していない(クラステンプレート引数控除中([over.match.class.deduct]))。
したがって、クラスのコンストラクタから合成された候補が推測されませんT
(推定できた転送基準からかのようにT
ように、左辺値の基準であることT&&
も左辺値基準である)、その代わりにのみ推測しますT
非基準として、その結果はT&&
常に右辺値参照。