この質問とコメント セクションに対する彼の回答で、Johannes Schaubは、渡されたよりも多くの引数を必要とする関数テンプレートに対してテンプレート型推定を実行しようとすると、「一致エラー」があると述べています。
template<class T>
void foo(T, int);
foo(42); // the template specialization foo<int>(int, int) is not viable
他の質問のコンテキストでは、関連するのは、関数テンプレートの型推定が成功するかどうか (および置換が行われるかどうか) です。
template<class T>
struct has_no_nested_type {};
// I think you need some specialization for which the following class template
// `non_immediate_context` can be instantiated, otherwise the program is
// ill-formed, NDR
template<>
struct has_no_nested_type<double>
{ using type = double; };
// make the error appear NOT in the immediate context
template<class T>
struct non_immediate_context
{
using type = typename has_no_nested_type<T>::type;
};
template<class T>
typename non_immediate_context<T>::type
foo(T, int) { return {}; }
template<class T>
bool foo(T) { return {}; }
int main()
{
foo(42); // well-formed? clang++3.5 and g++4.8.2 accept it
foo<int>(42); // well-formed? clang++3.5 accepts it, but not g++4.8.2
}
の最初の関数テンプレートfoo
をインスタンス化するときT == int
に、置換によって の直接のコンテキストにない無効な型が生成されますfoo
。これはハードエラーにつながります(これが関連する質問です。)
ただし、foo
そのテンプレート引数を推測させる場合、g++ と clang++ はインスタンス化が行われないことに同意します。Johannes Schaub が説明しているように、これは「一致エラー」があるためです。
質問: 「一致エラー」とは何ですか? また、規格のどこでどのように指定されていますか?
foo(42)
別の質問:とfoo<int>(42)
g++ に違いがあるのはなぜですか?
これまでに見つけた/試したこと:
[over.match.funcs]/7 と [temp.over] は、関数テンプレートのオーバーロード解決の詳細を説明しているようです。後者は、 のテンプレート パラメータの置換を義務付けているようですfoo
。
興味深いことに、[over.match.funcs]/7は、関数テンプレート (特殊化) の実行可能性をチェックする前に、[temp.over] で説明されているプロセスをトリガーします。同様に、型推論は、たとえば、デフォルトの関数引数を考慮しません (推論されないコンテキストにすることを除いて)。私の知る限り、生存率には関係ないようです。
もう 1 つの重要な側面は、型推定の指定方法です。T const&
単一の関数パラメーターに作用しますが、テンプレートパラメーターを含む/依存するパラメータータイプ( など)とそうでないタイプ( など)を区別する場所がわかりませんint
。
しかし、g++ では、テンプレート パラメーターを明示的に指定すること (ハード エラー) と、それらを推論させること (推論の失敗 / SFINAE) との間に違いがあります。なんで?