2016-08-19 15 views
1

異なる実装で同じことを行い、インターフェイスの関数名が異なる2つ以上のクラスのラッパーを記述したいとします。コンテキストに応じて、どちらか一方を選択しますが、私はそれらを簡単に切り替えることができるようにしたいと考えています。だから私はテンプレートの特殊化を使ってラッパーを書く。いいよ。しかし、私は問題に遭遇しました。私はそれがのtempaltedバージョンのために実行するためにそのコードを変更する必要があるだろうか、しかしテンプレートテンプレートの特殊化?

class A1 
{ 
public: 
    int f() 
    { 
     return 1; 
    } 
}; 

class A2 
{ 
public: 
    int g() 
    { 
     return 1; 
    } 
}; 


namespace detail 
{ 
    template <class T> int h(T& t) // general case 
    { 
     std::cout << "general" << "\n"; 
     return t.h(); 
    } 
    template <> int h<A1>(A1& a1)  // case for A1 
    { 
     std::cout << "A1" << "\n"; 
     return a1.f(); 
    } 
    template <> int h<A2>(A2& a2)  // case for A2 
    { 
     std::cout << "A2" << "\n"; 
     return a2.g(); 
    } 
} 

template <class T> 
class Wrapper 
{ 
public: 
    Wrapper(T& t) : t(t) {} 

    int operator()() 
    { 
     return detail::h<T>(t); 
    } 

    T& t; 
}; 

:彼らは通常のクラスだったら私の2クラスが、私はこのようなコードを書くことができ、テンプレートクラス...

ですA1およびA2?このことをしたと私が思いついた最高の(コンパイルされません):

template <class T> 
class A1 
{ 
public: 
    int f() 
    { 
     return 1; 
    } 
}; 

template <class T> 
class A2 
{ 
public: 
    int g() 
    { 
     return 1; 
    } 
}; 


namespace detail 
{ 
    template <class T, class U> int h(T<U>& t) // general case 
    { 
     return t.h(); 
    } 
    template <> int h<A1<U>>(A1<U>& a1)  // case for A1 
    { 
     return a1.f(); 
    } 
    template <> int h<A2<U>>(A2<U>& a1)  // case for A2 
    { 
     return a1.f(); 
    } 
} 

template <class T, class U> 
class Wrapper 
{ 
public: 
    Wrapper(T<U>& t) : t(t) {} 

    int operator()() 
    { 
     return detail::h<T,U>(t); 
    } 

    T<U>& t; 
}; 

だから、私は何とか矛盾のように聞こえるテンプレートの特殊化を、テンプレートにする必要があります。

編集

[OK]を..過負荷ソリューションの仕事をしようが、私は本当にそれを取得しないでください...

template <template <typename> class T, class U> 
class Wrapper 
{ 
public: 
    Wrapper(T<U>& t) : t(t) {} 

    template <template <typename> class T, typename U> 
    int h(T<U>& t) // general case 
    { 
     return t.h(); 
    } 

    template <typename U> 
    int h(A1<U>& a1)  // case for A1 
    { 
     return a1.f(); 
    } 
    template <typename U> 
    int h(A2<U>& a2)  // case for A2 
    { 
     return a2.g(); 
    } 

    T<U>& t; 
}; 
+0

'class'とメソッドに同じテンプレートパラメータ名を使用しないでください。これはC++では許可されていません(警告が必要です)。たとえば、を使用します。 'テンプレート int h(A1 &a1){...}'。 – Holt

答えて

4

は、テンプレートの特殊化への過負荷を好む:

template <template <typename> class T, typename U> 
int h(T<U>& t) // general case 
{ 
    return t.h(); 
} 

template <typename T> 
int h(A1<T>& a1)  // case for A1 
{ 
    return a1.f(); 
} 
template <typename T> 
int h(A2<T>& a2)  // case for A2 
{ 
    return a2.g(); 
} 
+0

ありがとうございますが、そのスニペットを少し拡張できますか?私は、これがどこに置かれるべきか、クラスが現在必要とするテンプレートパラメータを本当に理解していません。私はこの仕事をするためにいくつかの方法を試しましたが、誰もしませんでした。私の編集を参照してください。 –

+0

@lotolmencre元のテンプレート関数をネームスペースの詳細から取り出し、オーバーロードに変更しました。あなたはそれを認識し、オーバーロードをネームスピの詳細に戻すことができます。 Wrapperクラスの元のバージョンのoperator()内で、Wrapperのテンプレートパラメータに従って適切なオーバーロードが選択されていました。 – Aconcagua

関連する問題