7

私はC++で何か厄介なことを見つけましたが、オーバーヘッドなしでこれを回避するためのトリックがあるかどうかわかりません。問題は次のとおりです。

テンプレート関数の場合、次のようになります。

// Function declaration/definition
template<bool Option = false> void myFunction() 
{
    std::cout<<"Option = "<<Option<<std::endl;
}

// Then I can use :
myFunction<false>();
myFunction<true>();
myFunction(); // <- NO PROBLEM HERE

テンプレートクラスの場合:

// Class definition/declaration
template<bool Option = false> class MyClass
{
};

// Then I can use :
myClass<false> x;
myClass<true> y;
myClass z; // <- PROBLEM HERE : only "MyClass<> z;" will compile !

この動作の理由はなぜですか?それを避けるためのトリックはありますか?オプションのパラメータがテンプレートとして渡されたクラスの場合、これはエンドユーザーにとって不便であることがわかります。エンドユーザーはデフォルトの実装をテンプレートなしのクラスとして使用できるはずです...

4

2 に答える 2

8

この動作の理由はなぜですか?

これは、関数がオーバーロードされる可能性があり、型がオーバーロードできないためです。

関数呼び出しを作成すると、コンパイラーは、検出できるすべての関数のオーバーロードセットにその名前を入力し、渡された引数に一致する関数を特定します。これが関数テンプレートできれいに機能するように、テンプレートの引数の型をパラメーターから推測できるようになりました。タイプパラメータの推論は一般的に許可されているため、パラメータがデフォルトになっている場合でも機能します。

ただし、タイプはオーバーロードされません。myFunction<true>()myFunction<false>()は両方とも同じオーバーロードセットに参加する範囲に関連しており、別個myClass<true>myClass<false>無関係タイプです。タイプ名のオーバーロードに相当するものがないため、完全に特殊化されたテンプレートクラスに暗黙的に名前を付けるための特殊なケースを追加する動機はありません。パラメータを推測することはできないため、すべてデフォルトになっている場合にのみ、特別な構文になります。

それを避けるためのトリックはありますか?

一般に、テンプレートクラスのテンプレート引数の推定を取得する場合は、テンプレート関数ラッパーを提供できます(これはC ++ 11自動で最適に機能します)

template <bool Option=false> class MyClass {};
template <bool Option=false> MyClass<Option> make_my_class() {
    return MyClass<Option>();
}
// ...
auto z = make_my_class();

typedefそれ以外の場合は、 (Remyのコメントによると)使用するのが最善のオプションだと思います。

于 2012-10-06T02:07:59.043 に答える
3

myClassはクラステンプレートであり、クラスではありません。myClass<true>、または、のみmyClass<>がクラスです。

同様に、myFunctionは関数テンプレートであり、関数ではありません。ただし、テンプレート化された関数を呼び出す場合、テンプレート引数が推測される可能性があり、推測できる場合はテンプレート引数を明示的に指定する必要はありません。したがって、関数呼び出し式myFunction();は有効であり、最初の引数はとして推定されfalseます。関数の引数と照合するのではなく、デフォルトの引数のおかげで控除が行われるだけです。

于 2012-10-06T02:22:38.837 に答える