2011-12-22 6 views
2

私は型特性を作成して特定のクラスに特化する方法を理解していますが、私の場合はクラステンプレートを専門にしたいと思います。以下のコードはコンパイルされませんが、ユーザーがMyTemplatisedTypeで使用することを決定したタイプのMyTemplatisedClassのTraitの特殊化が機能するはずです。テンプレート化されたクラスのための形質の定義

class Traits 
{ 
public: 
    static bool someProperty(void) { return false; } 
}; 

template<typename Type> 
class MyTemplatisedClass 
{ 
}; 

template<typename Type> 
template<> 
class Traits< MyTemplatisedClass<Type> > 
{ 
public: 
    static bool someProperty(void) { return true; } 
}; 

int main(int argc, char* argv[]) 
{ 
    std::cout << Traits< MyTemplatisedClass<float> >::someProperty() <<std::endl; //This should be true 
    return 0; 
} 

これは可能ですか、それともあまりにも尋ねていますか?コンパイラによると、最初の問題は

error C2989: 'Traits' : class template has already been declared as a non-class template  

ですが、これはどのように修正できますか? それは私はそれがテンプレートではないクラスのために働く必要はありません任意の違いがあれば、テンプレート化されたものだけで大丈夫です。 編集:実際には、テンプレート化されたクラスとテンプレート化されていないクラスの両方で機能していればうれしいでしょう。

答えて

2

Traitsは、特殊化するためにテンプレートである必要があります。

特殊化では、空の行を削除します<>:これはテンプレート内にネストされたテンプレートではありません。

template <typename Type> //can only specialize templates 
class Traits 
{ 
public: 
    static bool someProperty(void) { return false; } 
}; 

template<typename Type> 
class MyTemplatisedClass 
{ 
}; 

template<typename Type> 
//template<> //Too much here 
class Traits< MyTemplatisedClass<Type> > 
{ 
public: 
    static bool someProperty(void) { return true; } 
}; 

しかし、あなたは1型引数を持つ任意のテンプレートの特殊化を意図した場合、その後、それは次のようになります。

template < template <class> class SomeTemplatizedType, class Type> 
//   ^^^^^^^^^^^^^^^^^^^^^^ 
//   names a template, not type 
class Traits< SomeTemplatizedType<Type> >; 
//   ^^^^^^^^^^^^^^^^^^^ ^
//    template name  | 
//        argument 
+0

ありがとうございました。あなたはすべて正しい答えを与えましたが、私は1つしか受け入れることができません。私はUncleBensと一緒に提供された追加情報については行くつもりです。 – PolyVox

+0

@UncleBens:両方のケースで例を挙げてもらえますか?私は、その違いが何であるか、あるいは1つの引数を持つ "any"テンプレートを特化することによって何を意味するのかをよく理解していません。 – Sarien

1

初期クラスは「基本ケース」である必要があり、つまり、任意の型引数を受け入れるためにテンプレート化されています。次に、あなたが呼びたい他の専門分野について心配することができます。実際使用は、このコンパイル時の計算では、あなたがそれ氷整数定数式にする必要がありますするために

template<typename T> class Traits 
{ 
public: 
    static bool someProperty(void) { return false; } 
}; 

template<typename Type> 
class MyTemplatisedClass 
{ 
}; 

template<typename Type> class Traits< MyTemplatisedClass<Type> > 
{ 
public: 
    static bool someProperty(void) { return true; } 
}; 

。たとえコンパイル時に値がわかるとしても、関数はconstexprにはなりません。現状では、私が行うことができない、例えば、

template<typename T> std::enable_if<Traits<T>::value, sometype> somefunc(); 
+0

ありがとうございました、あなたはすべて正しい答えを与えましたが、私は1つしか受け入れることができません。私はUncleBensと一緒に提供される追加情報については行くつもりです。 – PolyVox

1

問題は、クラスではなく、クラステンプレートとしてTraitsを宣言したということです。ちょうどtemplate<typename>Traitsの定義に追加し、スペシャライゼーションからスプリアスtemplate<>を削除すれば問題ありません。

template<typename>    // <--- Add this 
class Traits 
{ 
public: 
    static bool someProperty(void) { return false; } 
}; 

template<typename Type> 
class MyTemplatisedClass 
{ 
}; 

template<typename Type> 
// template<>     // <--- Remove this 
class Traits< MyTemplatisedClass<Type> > 
{ 
public: 
    static bool someProperty(void) { return true; } 
}; 

int main(int argc, char* argv[]) 
{ 
    std::cout << Traits< MyTemplatisedClass<float> >::someProperty() <<std::endl; //This should be true 
    return 0; 
} 
+0

ありがとうございました。あなたはすべて正しい答えを得ましたが、私は1つしか受け入れることができません。私はUncleBensと一緒に提供された追加情報については行くつもりです。 – PolyVox