Generalizing Mixins... c++'03

Discussion in 'C++' started by Werner, Apr 18, 2012.

  1. Werner

    Werner Guest

    Hi All,

    I've recently used mixins (without the courtesy of
    compilers supporting variadic templates) and were
    irritated by the fact that one had to always implement
    many constructors (one per base):

    Definition of Mixin: courtesy of http://www.drdobbs.com/cpp/184404445

    A mixin is a fragment of a class that is intended to be composed with other classes or mixins...

    For the problem I've come up with this solution (amongst others).

    What do you think?


    //////////////////////////////////////
    #include <iostream>

    struct Base
    {
    Base();
    Base( int i, int j ){}
    virtual void foo()
    {
    std::cout << "Base::foo()" << std::endl;
    }
    };

    template <class BaseT>
    struct Mixin : virtual BaseT
    {
    typedef BaseT base_type;
    //Problem
    //-Which constructor...? Always default... Generic!

    //Adds foo to any Base...
    virtual void foo()
    {
    std::cout << "Derived::foo()" << std::endl;
    }
    };

    //Solution? Something that calls base
    // constructor directly-always...

    template <class MixinT>
    struct GenMixin :
    virtual MixinT::base_type,
    MixinT
    {
    typedef typename MixinT::base_type base_type;
    GenMixin()
    {
    }
    template <class A0>
    GenMixin( A0 a0 )
    : base_type( a0 )
    //Mixin always has default only...
    {
    }
    template <class A0, class A1>
    GenMixin( A0 a0, A1 a1 )
    : base_type( a0, a1 )
    //Mixin always has default only...
    {
    }
    };

    typedef GenMixin<Mixin<Base> > MyMixin;
    int main()
    {
    MyMixin( 1, 2 ).foo();
    }
    Werner, Apr 18, 2012
    #1
    1. Advertising

  2. Werner

    Werner Guest

    On Wednesday, April 18, 2012 4:21:51 PM UTC+2, Werner wrote:
    > Hi All,
    >
    > I've recently used mixins (without the courtesy of
    > compilers supporting variadic templates) and were
    > irritated by the fact that one had to always implement
    > many constructors (one per base):
    >
    > Definition of Mixin: courtesy of http://www.drdobbs.com/cpp/184404445
    >
    > A mixin is a fragment of a class that is intended to be composed with other classes or mixins...
    >
    > For the problem I've come up with this solution (amongst others).
    >
    > What do you think?
    >
    >
    > //////////////////////////////////////
    > #include <iostream>
    >
    > struct Base
    > {
    > Base();
    > Base( int i, int j ){}
    > virtual void foo()
    > {
    > std::cout << "Base::foo()" << std::endl;
    > }
    > };
    >
    > template <class BaseT>
    > struct Mixin : virtual BaseT
    > {
    > typedef BaseT base_type;
    > //Problem
    > //-Which constructor...? Always default... Generic!
    >
    > //Adds foo to any Base...
    > virtual void foo()
    > {
    > std::cout << "Derived::foo()" << std::endl;
    > }
    > };
    >
    > //Solution? Something that calls base
    > // constructor directly-always...
    >
    > template <class MixinT>
    > struct GenMixin :
    > virtual MixinT::base_type,
    > MixinT
    > {
    > typedef typename MixinT::base_type base_type;
    > GenMixin()
    > {
    > }
    > template <class A0>
    > GenMixin( A0 a0 )
    > : base_type( a0 )
    > //Mixin always has default only...
    > {
    > }
    > template <class A0, class A1>
    > GenMixin( A0 a0, A1 a1 )
    > : base_type( a0, a1 )
    > //Mixin always has default only...
    > {
    > }
    > };
    >
    > typedef GenMixin<Mixin<Base> > MyMixin;
    > int main()
    > {
    > MyMixin( 1, 2 ).foo();
    > }


    I know the solution above is ugly, but I found
    it an interesting exercise. It only works well
    if the mixin has a default constructor. Using the
    new standard this is what I've come up with (which
    I suppose is the solution people use nowadays...).

    Kind regards,

    Werner

    #include <iostream>

    struct Base
    {
    Base()
    {
    std::cout << "Base() called." << std::endl;
    }
    Base( int i, int j )
    {
    std::cout << "Base ( " << i << ", " << j << " ) called." << std::endl;
    }
    virtual void foo()
    {
    std::cout << "Base::foo()" << std::endl;
    }
    };

    template <class BaseT>
    struct Mixin : virtual BaseT
    {
    template <typename ...BaseArgs>
    Mixin( const char*, BaseArgs&&... args )
    : BaseT( std::forward<BaseArgs>(args)... )
    {
    }
    //Adds foo to any Base...
    virtual void foo()
    {
    std::cout << "Derived::foo()" << std::endl;
    }
    };

    typedef Mixin<Base> MyMixin;
    int main()
    {
    MyMixin( "Hallo", 10, 20 ).foo();
    }
    Werner, Apr 19, 2012
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Aleksandr Dubinskiy

    generalizing template code

    Aleksandr Dubinskiy, Jul 2, 2003, in forum: C++
    Replies:
    3
    Views:
    437
    Aleksandr Dubinskiy
    Jul 4, 2003
  2. Szabolcs
    Replies:
    7
    Views:
    328
    Gianni Mariani
    Jan 20, 2008
  3. ago
    Replies:
    0
    Views:
    289
  4. trans.  (T. Onoma)

    Generalizing and Organizing Code

    trans. (T. Onoma), Nov 23, 2004, in forum: Ruby
    Replies:
    4
    Views:
    118
    trans. (T. Onoma)
    Nov 25, 2004
  5. Replies:
    2
    Views:
    130
    Steven D'Aprano
    Sep 1, 2013
Loading...

Share This Page