std::reference_wrapper
がないoperator<
ため、唯一の方法はメンバーref_wrapper<ref_wrapper
を介することです。ref_wrapper
operator T& () const noexcept;
ご存知のように、次のとおりですstd::string
。
typedef basic_string<char> string;
関連する宣言string<string
は次のとおりです。
template<class charT, class traits, class Allocator>
bool operator< (const basic_string<charT,traits,Allocator>& lhs,
const basic_string<charT,traits,Allocator>& rhs) noexcept;
このstring<string
関数宣言テンプレートは、一致するstring
=によってインスタンス化され、これは=などbasic_string<charT,traits,Allocator>
に解決されます。charT
char
std::reference_wrapper
(またはその (ゼロ) 基底クラスのいずれか) が一致しないためbasic_string<charT,traits,Allocator>
、関数宣言テンプレートを関数宣言にインスタンス化できず、オーバーロードに参加できません。
ここで重要なのは、非テンプレートプロトタイプがないことです。operator< (string, string)
問題を示す最小限のコード
template <typename T>
class Parametrized {};
template <typename T>
void f (Parametrized<T>);
Parametrized<int> p_i;
class Convertible {
public:
operator Parametrized<int> ();
};
Convertible c;
int main() {
f (p_i); // deduce template parameter (T = int)
f (c); // error: cannot instantiate template
}
与える:
In function 'int main()':
Line 18: error: no matching function for call to 'f(Convertible&)'
標準引用
14.8.2.1 関数呼び出しからのテンプレート引数の推定 [temp.deduct.call]
テンプレート引数推定は、以下で説明するように、各関数テンプレート パラメーターの型 (call it P
) と呼び出しの対応する引数の型 (call it ) を比較することによって行われA
ます。
(...)
一般に、演繹プロセスは、演繹されたものを (上記のように型が変換された後に)A
同一にするテンプレート引数値を見つけようとします。ただし、違いが認められる 3 つのケースがあります。A
A
- 元
P
の型が参照型の場合、推論されA
た型 (つまり、参照によって参照される型) は、変換された型よりも cv 修飾されている可能性がありますA
。
これは の場合であることに注意してくださいstd::string()<std::string()
。
- 変換されたものは、修飾変換 (4.4) を介して推定に変換
A
できる別のポインターまたはメンバー型へのポインターにすることができます。A
以下のコメントを参照してください。
- が
P
クラスでP
、形式がsimple-template-idの場合、変換A
された は deduced の派生クラスになることができますA
。
コメント
これは、この段落で次のことを意味します。
14.8.1 明示的なテンプレート引数指定 [temp.arg.explicit] /6
暗黙的な変換 (第 4 節) は、関数の引数に対して実行され、対応する関数パラメーターの型に変換されます (パラメーターの型に、テンプレート引数推定に関与するテンプレート パラメーターが含まれていない場合)。
ifは、前に引用したテキストと直接矛盾するため、 if および only if と見なすべきではありません。