3

この質問とコメント セクションに対する彼の回答で、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) との間に違いがあります。なんで?

4

1 に答える 1

2

私が要約したのは、14.8.2.1p1 で説明されているプロセスです。

テンプレート引数の推定は、以下で説明するように、各関数テンプレート パラメーターの型 (P と呼びます) を呼び出しの対応する引数の型 (A と呼びます) と比較することによって行われます。

私たちの場合、P には が(T, int)あり、A には があり(int)ます。Tに対してある P/A の最初のペアについては、(14.8.2.5 で説明されているプロセスによって) にint一致Tさせることができます。intしかし、2 番目の「ペア」についてはint、対応するものはありません。したがって、この「ペア」について控除を行うことはできません。

これにより、14.8.2.5p2 により、「どの P/A ペアに対しても型推定ができない場合、...、テンプレート引数の推定は失敗します。」.

これで、テンプレート引数を関数テンプレートに代入することはできなくなります。

これはおそらく標準 (IMO) でより正確に記述できますが、これが Clang と GCC の実際の動作に一致するように実装できる方法であり、標準の合理的な解釈のように思われます。

于 2014-03-14T21:18:37.363 に答える