13

コンパイラがそれ自体で型を設定できる関数テンプレートがある場合typename T、次のように関数を呼び出すときに型を明示的に記述する必要はありません。

template < typename T > 
T min( T v1, T v2 ) {
   return ( v1 < v2 ) ? v1: v2;
}
int i1 = 1, i2 = 2; int i3 = min( i1, i2 ); //no explicit <type> 

しかし、次のような 2 つの異なる型名を持つ関数テンプレートがあるとします。

template < typename TOut, typename TIn >
TOut round( TIn v ) {
   return (TOut)( v + 0.5 );
}
double d = 1.54;
int i = round<int>(d); //explicit <int>

常に少なくとも 1 つの型名を指定する必要があるというのは本当ですか? その理由は、C++ が異なる戻り値の型間で関数を区別できないためだと思います。

しかし、void 関数を使用して参照を渡す場合も、戻り値の型名を明示的に指定してはなりません。

template < typename TOut, typename TIn > 
void round( TOut & vret, TIn vin ) {
   vret = (TOut)(vin + 0.5);
}
   double d = 1.54;
   int i; round(i, d); //no explicit <int>

結論として、return を伴う関数を避け、voidテンプレートを作成するときに参照を介して戻る関数を優先する必要がありますか? または、戻り値の型を明示的に記述しないようにする可能性はありますか? テンプレートの「型推論」のようなもの。C++0xで「型推論」は可能ですか?

4

3 に答える 3

19

オーバーロードの解決は、関数の引数に基づいてのみ行われます。戻り値はまったく使用されません。引数に基づいて戻り値の型を決定できない場合は、明示的に指定する必要があります。

参照パラメーターを介して値を「返す」という道はたどりません。これにより、呼び出しコードが不明確になります。たとえば、私はこれを好みます:

double x = round<double>(y);

これについて:

double x;
round(x, y);

後者の場合、入力と出力を混同しやすく、変更されていることがまったく明確ではないためxです。

の特定のケースではround、とにかく 1 つまたは 2 つの型だけが必要になる可能性TOutがあるため、そのテンプレート引数をそのままにしておくことができます。

template<typename TIn>
int roundToInt(TIn v) {
    return (int)(v + 0.5);
}

タイプが何に使用されるかが明確であるため、よりroundToInt(x)も少し明確です。round<int>(x)int

于 2010-05-14T11:31:34.107 に答える
3

結論は、return を伴う関数を避け、テンプレートを記述するときに参照を介して戻る void 関数を優先することです。

いいえ、なぜですか?あなたは何を得ますか?型推論のみ (したがって、記述するコードが少なくなります)。しかし、値を代入するというより論理的な構文が失われます (したがって、より多くのコードを記述する必要があります)。つまり、1 つが得られ、もう 1 つが失われました。全体的にメリットが感じられません。

テンプレートの種類を明示的に指定することも役立つlexical_cast場合があります: の場合を考えてみましょう。戻りテンプレートの型を指定しないと混乱します。

于 2010-05-14T11:39:11.717 に答える
2

他の人が言ったことに加えて、CスタイルのキャストよりもC++のキャストを好むべきだと言ってみましょう。

vret = (TOut)(vin + 0.5);

vret = static_cast<TOut>(vin + 0.5);

無関係なタイプを変換しようとすると、静的キャストは常に失敗します。これはデバッグに役立ちます。

于 2010-05-14T11:55:16.477 に答える