1

これは、この記事 (5 ページ)によって動機付けられました。

template<class T> 
T const &f(T const &a, T const &b){
    return (a > b ? a : b);
}

template int const &f<int>(int const &, int const &);

int main(){
    int x = 0, y = 0;
    short s = 0;
    f(x, y);     // OK
    f(x, s);     // Is this call well-formed?
}

呼び出しは'f(x, s)'整形式ですか? 関数テンプレート'f'は明示的にインスタンス化されるため、標準の変換が適用され、明示的な特殊化への呼び出しに一致する'short s'ように変換されると想定しました。しかし、これは形式が悪いように見えますか?'int''f<int>'

この文脈で適用される規則について述べている規格の部分はどれですか?

4

3 に答える 3

5

いいえ、呼び出しf(x, s)は整形式ではありません。使用する特殊化を明示的に指定しないため、コンパイラは引数推定を使用して関数テンプレートのインスタンス化を試みます。と の型が異なるため、あいまいであるためx、これは失敗します。sT

該当するルールは、13.3.1 のオーバーロード解決プロセスの仕様にあります。

候補が関数テンプレートである場合はそれぞれ、テンプレートの実引数推論 (14.8.3、14.8.2) を使用して候補関数テンプレートの特殊化が生成されます。これらの候補は、通常の方法で候補関数として処理されます。

14.8.3/1 も関連しています。

関数テンプレートごとに、引数の推定とチェックが成功した場合、テンプレート引数 (推定および/または明示) を使用して、オーバーロード解決で使用される候補関数セットに追加される単一の関数テンプレートの特殊化をインスタンス化します。特定の関数テンプレートで引数推定が失敗した場合、そのテンプレートの候補関数のセットにそのような関数は追加されません。

関数テンプレートは に対して明示的にインスタンス化されていますT = intが、コンパイラは、テンプレート引数推定を実行して何が必要かを判断するまで、このインスタンス化を使用する必要があることを知りませんT

于 2010-09-16T05:18:14.730 に答える
3

呼び出しf(x, s)は構文的に整形式ですが、コンパイラはTそれからテンプレート パラメーターを推測できintませんshort。テンプレートをインスタンス化しても役に立ちません。これは、コンパイラがその特殊化をコンパイルして、生成されたオブジェクト ファイルに追加することを示すだけです。

呼び出しを自動的ににキャストsする場合は、 を使用します。intf<int>(x, s)

于 2010-09-16T04:09:08.747 に答える
1

明示的にインスタンス化された特殊化には、より高い優先度や優遇措置はありません。インスタンス化の時点から完全に存在するだけです。ライブラリに便利です。

コンパイラは、どの引数を変換するかを単純に判断できず、余分な宣言がない場合と同じようにスタックします。

ちなみに、変換された引数への参照を返すと、一時的な有効期限が切れるとぶら下がります。引数が異なる型への参照である場合、戻り値を適切に形成する方法はありません。

ここに私の更新がありminます:

#include <type_traits>

template< typename A, typename B >
typename std::common_type< A, B >::type // cannot return ref
my_min( A const &a, B const &b ) {
    return a < b? a : b;
}

 // enable_if< is_same< A, B > > the old, return-by-reference impl

int main() {
    int q = my_min( short(5), long(3) );
}
于 2010-09-16T05:19:29.030 に答える