C++ 动态编译时混合

C++ 动态编译时混合,c++,c++11,mixins,C++,C++11,Mixins,我试图找到一种在编译时定义动态混合的方法。我目前有一个非常粗糙的解决方案,它只能部分实现我想要的,但我不确定如何改进它 我知道使用Type的更多的C++类解决方案,但是它们需要静态地定义所有的类型,我试图避免。p> 这只是一个思想练习,学习C++更好,我确信我当前的实现不是很好的C++。欢迎提出任何改进建议或尝试不同想法 我目前实施的主要问题是: 每个mixin类只知道它自己以及层次结构中比它自己低的类。我希望每个mixin类能够返回一个具有不同底层类型的新mixin。在下面的示例代码中,我希

我试图找到一种在编译时定义动态混合的方法。我目前有一个非常粗糙的解决方案,它只能部分实现我想要的,但我不确定如何改进它

我知道使用Type的更多的C++类解决方案,但是它们需要静态地定义所有的类型,我试图避免。p> <>这只是一个思想练习,学习C++更好,我确信我当前的实现不是很好的C++。欢迎提出任何改进建议或尝试不同想法

我目前实施的主要问题是:

  • 每个mixin类只知道它自己以及层次结构中比它自己低的类。我希望每个mixin类能够返回一个具有不同底层类型的新mixin。在下面的示例代码中,我希望
    PrintOnce
    能够有一个返回
    printTworth
    对象的方法
  • 这个想法的任何使用都需要有一个标题包含顺序。开始时的所有锅炉板代码都需要在一个标题中,然后需要定义所有的mixin类,最后可以定义
    make_mixed
    函数。当前,在
    make\u mixed
    函数之后定义的任何mixin都将被忽略
  • 宏和实现的一般缺陷
我很抱歉这么长,但这是我能想到的最简单的例子

谢谢你的帮助

#include <string>
#include <vector>
#include <iostream>

using namespace std;

template<class Underlying>
struct Printer
{
    Printer(const Underlying &val) : val_(val) {}

    Underlying get_val() { return val_; }

  private:
    Underlying val_;
};

#define CURRENT_NUMBER_MIXED_IN_CLASSES() \
    MixinCount<0, __LINE__>::value

#define INCREMENT_MIXIN_CLASS_COUNTER() \
    template<int id>                                               \
    struct MixinClassCounter< CURRENT_NUMBER_MIXED_IN_CLASSES(), id>    \
    {                                                                   \
        static const bool is_defined = true;                            \
    }

template< bool b, typename i, typename j >
struct select_value;

template<class i, class j>
struct select_value<true, i, j>
{
    static const int value = i::value;
};

template<class i, class j>
struct select_value<false, i, j>
{
    static const int value = j::value;
};

template<int i>
struct IntToVal
{
    static const int value = i;
};

namespace
{
    template<int count, int id>
    struct MixinClassCounter
    {
        static const bool is_defined = false;
    };

    template<int count, int id>
    struct MixinCount
    {
        static const int value = select_value<MixinClassCounter<count, id>::is_defined,
                                              MixinCount<count + 1, id>,
                                              IntToVal<count> >::value;
    };

    template<class Underlying, int i>
    struct MixinBuilder {};

    template<class Underlying>
    struct MixinBuilder<Underlying, 0>
    {
        typedef Printer<Underlying> type;
    };
    INCREMENT_MIXIN_CLASS_COUNTER();
}

#define DECLARE_MIXIN_BEGIN(name) \
    template<class Base> \
    struct name : Base   \
    {                    \
        template<class Underlying>                  \
        name(const Underlying &val) : Base(val) {}

#define DECLARE_MIXIN_END(name)                 \
    };                                          \
    namespace                                   \
    {                                               \
        template<class Underlying>                                         \
        struct MixinBuilder<Underlying, CURRENT_NUMBER_MIXED_IN_CLASSES()> \
        {                                                                   \
            typedef name< typename MixinBuilder<Underlying, CURRENT_NUMBER_MIXED_IN_CLASSES() - 1>::type > type; \
        };                                                                  \
        INCREMENT_MIXIN_CLASS_COUNTER();                                    \
    }                                                                       \


DECLARE_MIXIN_BEGIN(PrintOnce)
void print_once()
{
    cout << Base::get_val() << endl;
}
DECLARE_MIXIN_END(PrintOnce)

DECLARE_MIXIN_BEGIN(PrintTwice)
void print_twice()
{
    cout << Base::get_val() << endl;
    cout << Base::get_val() << endl;
}
DECLARE_MIXIN_END(PrintTwice)

template<class T>
typename MixinBuilder<T, CURRENT_NUMBER_MIXED_IN_CLASSES() - 1>::type make_mixed(const T &val)
{
    return typename MixinBuilder<T, CURRENT_NUMBER_MIXED_IN_CLASSES() - 1>::type(val);
}

int main()
{
    string test("this is a test");
    auto printable_string = make_mixed(test);

    printable_string.print_once();
    printable_string.print_twice();
}
#包括
#包括
#包括
使用名称空间std;
模板
结构打印机
{
打印机(常量和val):val_(val){}
底层get_val(){return val;}
私人:
潜在价值;
};
#在\u类()中定义当前\u编号\u混合\u\
MixinCount::value
#定义增量\u混合\u类\u计数器()\
模板\
结构MixinClassCounter\
{                                                                   \
静态常数布尔值定义为真\
}
模板
结构选择_值;
模板
结构选择值
{
静态常量int value=i::value;
};
模板
结构选择值
{
静态常量int value=j::value;
};
模板
结构IntToVal
{
静态常数int值=i;
};
名称空间
{
模板
结构MixinClassCounter
{
静态常量布尔值为_defined=false;
};
模板
结构混合计数
{
静态常量int值=选择值::值;
};
模板
结构MixinBuilder{};
模板
结构混合生成器
{
打印机类型;
};
增量混合类计数器();
}
#定义DECLARE\u MIXIN\u BEGIN(名称)\
模板\
结构名称:Base\
{                    \
模板\
名称(const-underlined&val):基(val){}
#定义DECLARE\u MIXIN\u END(名称)\
};                                          \
名称空间\
{                                               \
模板\
结构混合生成器\
{                                                                   \
typedef nametype\
};                                                                  \
增量混合类计数器()\
}                                                                       \
声明混合开始(打印一次)
作废打印一次()
{

cout这里有一个没有宏的更干净的解决方案:

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

template <typename T>
struct RefWrapper
{
    T *self;
    RefWrapper () : self (nullptr) {abort ();} // should never be called
    RefWrapper (T &self) : self (&self) {}
};


template <typename T>
struct PrintOnce : virtual RefWrapper<T>
{
    PrintOnce () {}             // workaround gcc 4.6 bug
    void print_once () {cout << *RefWrapper<T>::self << endl;}
};


template <typename T>
struct PrintTwice : virtual RefWrapper<T>
{
    PrintTwice () {}            // workaround gcc 4.6 bug
    void print_twice ()
    {
        cout << *RefWrapper<T>::self << endl;
        cout << *RefWrapper<T>::self << endl;
    }
};


template <typename T, typename... Args>
struct Mixed : Args...
{
    Mixed (T &self) :
        RefWrapper<T> (self),
        Args ()... {}

    Mixed (const Mixed &copy) :
        RefWrapper<T> (*copy.self),
        Args ()... {}
};


template <template <typename U> class Mixin, typename T>
Mixed<T, Mixin<T> > add_mixin (T &original)
{
    return Mixed<T, Mixin<T> > (original);
}


template <template <typename U> class Mixin, typename T,
          typename... OtherMixins>
Mixed<T, OtherMixins..., Mixin<T> >
add_mixin (Mixed<T, OtherMixins...> &original)
{
    return Mixed<T, OtherMixins..., Mixin<T> > (*original.self);
}


int main ()
{
    string foo = "test";

    auto p1 = add_mixin<PrintOnce> (foo);
    p1.print_once ();

    auto p2 = add_mixin<PrintTwice> (p1);
    p2.print_once ();
    p2.print_twice ();
}
#包括
#包括
使用std::cout;
使用std::endl;
使用std::string;
模板
结构参照包装器
{
T*self;
RefWrapper():永远不应调用self(nullptr){abort();}//
RefWrapper(T&self):self(&self){}
};
模板
结构PrintOnce:虚拟RefWrapper
{
PrintOnce(){}//解决GCC4.6错误的方法
void print_once(){cout这不是一个解决方案,但是Boost预处理器库可能会帮助您实现您想要做的事情。