2016-06-14 1 views
1

を実装するC++インタフェースをミックスインを指示します。私の理解では、これはミックスインのためのものです。はどのようにインターフェースし、それを実装したクラスを持っていることが

など。 foo()は、ある条件でパラメータ値を変更する必要があります。ここで私はそれを行う方法です。

template <typename T> 
class Mixin : public T 
{ 
public: 
    virtual void foo(Enum & a) { 
     T::foo(a); 
     if (a == X){ 
      a = Y; 
     } 
    } 
}; 

問題は、私はこのようなインタフェースクラスまたはそれらのtypedef定義された識別子にスコープ接頭辞を書くいずれかの場合を除き、それはコンパイルされません、次のとおりです。

template <typename T> 
class Mixin : public T 
{ 
public: 
    typedef InterfaceA::Enum Enum; 
    virtual void foo(Enum & a) { 
     T::foo(a); 
     if (a == InterfaceA::X){ 
      a = InterfaceA::Y; 
     } 
    } 
}; 

にですインタフェースの定義から生じるタイプがほとんどない場合、大きな問題ではありません。しかし、多くの場合、それは醜くなることができます。ミックスインがInterfaceAオブジェクトを設計しているという事実をコードに反映させたいと思います。残念なことにInterfaceAのMixinを継承することは、私が避けるほうがいい「恐ろしいダイヤモンド」を導入する。それは可能ですか?

答えて

0

EnumXYなどの

何かが依存型名でなければなりません。

そして、static_assertを使用して強制的に継承することができます。

template <typename T> 
class Mixin : public T 
{ 
public: 
    static_assert(std::is_base_of<InterfaceA, T>::value, 
        "T should inherit from InterfaceA"); 

    virtual void foo(typename T::Enum & a) { 
     T::foo(a); 
     if (a == T::X){ 
      a = T::Y; 
     } 
    } 
}; 
+0

static_assertは素晴らしいですが、C++ 11以前の環境ではどのようなことをお勧めしますか? – peti

+0

@peti:[how-to-do-static-assert-with-macros](http://stackoverflow.com/questions/14621968/how-to-do-static-assert-with-macros)をご覧ください。 – Jarod42

0

私はあなたが仮想継承を使うべきだと考えます。これは "恐ろしいダイヤモンド"の問題を避ける必要があります。

class InterfaceA 
{ 
    public: 
     enum Enum { X, Y, Z }; 
     virtual void foo(Enum &) = 0; 
     virtual void bar() = 0; 
}; 

class ClassA : public virtual InterfaceA 
{ 
    public: 
     virtual void foo(Enum & a) { 
     a = X; 
     } 
     virtual void bar() { 
     } 
}; 

template <typename T> 
class Mixin : public T, public virtual InterfaceA 
{ 
    public: 
     virtual void foo(Enum & a) { 
     T::foo(a); 
     if (a == X){ 
      a = Y; 
     } 
     } 
}; 


int main() 
{ 
    Mixin<ClassA> m; 

    return 0; 
} 
関連する問題