2012-10-06 11 views
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 ! 

は、なぜ、この行動の理由は? これを回避する方法はありますか? テンプレートとして渡されたoptionnalパラメータを持つクラスの場合、私はエンドユーザーのために、これは便利ではない見つける:彼はノーテンプレートクラスとしてデフォルトの実装を使用することができるはず...

+0

"*これを避けるための方法はありますか?*"それ以外の新しいタイプの名前を作成することを検討し、すべてのコンストラクタを転送することを検討している場合を除きます。 – ildjarn

+4

また、継承の代わりにtypedefを使用するだけです。 'typedef myClass myClassDef; –

+0

@Remy:ああ、そうです。私の脳はその日に終わったと思う。 – ildjarn

答えて

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のコメントに従って)を使用するのが最適なオプションです。

3

myClassは、クラステンプレートではなく、クラスです。 myClass<true>またはmyClass<>のみがクラスです。

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

関連する問題