3

次の 2 つの構造体を指定すると、ネストされた「ネストされた」クラスの両方から派生し、派生オブジェクトから foo() と bar() を呼び出すことができます。

struct WithNested1 {
    template<class T> struct Nested {
        void foo();
    };
};

struct WithNested2 {
    template<class T> struct Nested {
        void bar();
    };
};

struct Test : WithNested1::Nested<Test>,
              WithNested2::Nested<Test>
{

};

Test test;
test.foo();
test.bar();


しかし、両方の外部クラスが可変個引数のテンプレート引数として渡された場合、それらからどのように派生しますか?

たとえば、これはコンパイルに失敗します。

template<typename... Ts>
struct Test : Ts::template Nested<Test>...
{

};

Test<WithNested1, WithNested2> test;
test.foo();
test.bar();

エラー: 'foo': 'Test' のメンバーではありません
エラー: 'bar': 'Test' のメンバーではありません

奇妙なことに、foo() と bar() の呼び出しを削除するとコンパイルされます。

4

3 に答える 3

3
template <typename... Ts>                                                          
struct Test : Ts::template Nested<Test<Ts...>>...                                  
{                                                                                  

};  

これは上記と同じ答えですが、それがどのように機能するかを説明したいと思いました。最初の例Testにはテンプレートパラメーターがありません(コンパイラーは警告する必要があります)が、それを与える必要があります。CRTP のポイントは、型と同じテンプレート パラメーターから継承したクラスを与えることです。これにより、テンプレート パラメーターを介してメソッドとメンバーにアクセスできます。この場合のタイプは、Test<Ts...>それを渡す必要があるためです。@asheplerがすでに指摘しているように、通常は単独で使用できますがTest、クラス内に入るまでは範囲外です。

これは、あなたが望むことを行うためのよりクリーンな方法だと思います。

template <typename T>                                                              
struct A {                                                                         
    void bar (){                                                                   
        static_cast<T*>(this)->val = 3;                                            
    }                                                                              
};                                                                                 

template <typename T>                                                              
struct B {                                                                         
    void foo (){                                                                   
        static_cast<T*>(this)->val = 90;                                           
    }                                                                              
};                                                                                 


template <template<class> class ... Ts>                                            
struct Test : Ts<Test<Ts...>>...                                                   
{                                                                                  
    int val;                                                                       
};                                                                                 

int main() {                                                                       
    Test<A,B> test;                                                                
    test.foo();                                                                    
    test.bar();                                                                    
    return 0;                                                                      
}  
于 2013-11-10T04:09:59.943 に答える
2

Testの省略形として使用できる「注入されたクラス名」は、トークンまでクラススコープが開始されないため、Test<Ts...>使用しようとした場所にスコープがありません。Nested<Test>{

使用する

template<typename... Ts>
struct Test : public Ts::template Nested<Test<Ts...>>...
{
};
于 2013-11-10T04:10:07.697 に答える