2017-07-21 10 views
2

私はいくつかのレガシーコードを処理する方法を見つけようとしています。特定のパラメータでインスタンス化したときに、異なる引数をそのベースに渡すようにコンストラクタを特化したいと思うテンプレート化されたクラスがあります。テンプレートテンプレートパラメータのテンプレートクラスコンストラクタを特殊化する

template<typename T, typename U> 
class A : public U { 
public: 
    A(T &t, bool b); 
    // Other member functions 
} 

template<typename T, typename U> 
A<T, U>::A(T &t, bool b) 
    : U(t, b) {} 

私はUが特定の(テンプレート)クラスである場合、このコンストラクタのthebehaviorを変更する必要があります。

template<typename Z> 
class S; 

template<typename T> 
template<typename Z> 
A<T, S<Z>>::A(T &t, bool b) 
    : S<Z>(t, b, false) {} 

これは可能ですか?クラステンプレートの特殊化は、新しいクラスを再定義しなければ実行できないことはわかっています。しかし、私はむしろこの振る舞いを専門にするだけで、このクラスの他のメンバ関数ではありません。U

+0

見て:あなたが必要https://stackoverflow.com/questions/11310898/how-do-i-get-the-type-of-a-variable –

+0

C++ 98ソリューション、またはC++ 11/C++ 14ソリューションも受け入れますか? – max66

+0

C++ 11がベストだろうが、私も14を取るだろう – shane

答えて

0

A Cを++ 11ソリューションは、USベースのタイプである場合、第1または第2のコンストラクタを有効にして、SFINAEに基づくことができます。

これを行うには、型があるかどうかを検出する型の特性を開発することが役に立ちます(S)。

template <typename V = U> 
A(T & t, bool b, 
    typename std::enable_if<false == isS<V>::value>::type * = nullptr) 
    : U(t, b) 
{ std::cout << "generic A constructor" << std::endl; } 

template <typename V = U> 
A(T & t, bool b, 
    typename std::enable_if<true == isS<V>::value>::type * = nullptr) 
    : U(t, b, false) 
{ std::cout << "S specific A constructor" << std::endl; } 

を次のように例

template <typename> 
struct isS : public std::false_type 
{ }; 

template <typename T> 
struct isS<S<T>> : public std::true_type 
{ }; 

isSとによって、あなたはSのテンプレート引数が必要な場合は、あなたがの特殊化を定義することができます(Aクラスのボディに)あなたのコンストラクタを書くことができますisS

template <typename T> 
struct isS<S<T>> : public std::true_type 
{ using type = T; }; 

をたどり、typename isS<V>::typeとしてそれを使用して。

フル実施例

#include <vector> 
#include <iostream> 
#include <type_traits> 

template <typename T> 
struct S 
{ 
    S (T const &, bool, bool) 
    { std::cout << "S constructor" << std::endl; } 
}; 

template <typename> 
struct isS : public std::false_type 
{ }; 

template <typename T> 
struct isS<S<T>> : public std::true_type 
{ }; 

template <typename T, typename U> 
struct A : public U 
{ 
    template <typename V = U> 
    A(T & t, bool b, 
    typename std::enable_if<false == isS<V>::value>::type * = nullptr) 
     : U(t, b) 
    { std::cout << "generic A constructor" << std::endl; } 

    template <typename V = U> 
    A(T & t, bool b, 
    typename std::enable_if<true == isS<V>::value>::type * = nullptr) 
     : U(t, b, false) 
    { std::cout << "S specific A constructor" << std::endl; } 
}; 

int main() 
{ 
    long l { 0L }; 

    // print "generic A constructor" 
    A<long, std::vector<int>> alv(l, true); 

    // print "S constructor>" and "S specific A constructor" 
    A<long, S<int>>   als(l, true); 
} 
0

各クラスのid関数が異なる値を返すように、各クラスにidという関数を追加できます。それが渡されたときは、その後、どのようなタイプのid関数によって返されたことができますが、このクラスを特化させたくない場合は

0

、あなたが継承したいものを特化することができます。

template<typename T, typename U> 
class A_impl : public U { 
public: 
    A_impl(T &t, bool b) : U(t, b) { } 
}; 

template<typename T, typename Z> 
class A_impl<T,S<Z> > : public S<Z> { 
public: 
    A_impl(T &t, bool b) : S<Z>(t, b, false) { } 
}; 

template<typename T, typename U> 
class A : public A_impl<T,U> { 
public: 
    using A_impl<T,U>::A_impl; // C++11 : inherit A_impl's constructor here 
    A(T &t, bool b) : A_impl<T,U>(t, b) {} // or C++98 calling it 
}; 
関連する問題