1

I have an interface and a class implementing it:

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

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

I need to extend the functionality of an InterfaceA implementing class in one aspect. In my understanding this is what mixins are for.

E.g. foo() should change its parameter value on some condition. Here is how I do it:

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

The problem is, it won't compile unless I either write scope prefixes to identifiers defined in the interface class or typedef them like this:

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;
        }
    }
};

It's not a big deal if there are few such types coming from the interface definition. But if there are many, it can become ugly. I would like the code to reflect the fact that a Mixin manipulates an InterfaceA object by design. Unfortunately inheriting Mixin from InterfaceA introduces a 'dreaded diamond' which I'd better avoid. Is that possible?

peti
  • 55
  • 4

2 Answers2

0

I suppose you should use virtual inheritance; this should avoid "dreaded diamond" problem.

Something like

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;
 }
max66
  • 65,235
  • 10
  • 71
  • 111
0

Enum, X and Y should be dependent typename.

And you may use static_assert to force inheritance.

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;
        }
    }
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • static_assert is cool, but what would you suggest in a pre-C++11 environment? – peti Sep 13 '16 at 13:11
  • @peti: You may look at [how-to-do-static-assert-with-macros](http://stackoverflow.com/questions/14621968/how-to-do-static-assert-with-macros) – Jarod42 Sep 13 '16 at 13:19