动态编译时混入
我试图想出一种在编译时定义动态 mixins 的方法。我目前有一个非常老套的解决方案,只能部分实现我想要的功能,但我不知道如何改进它。
我知道更多类似 C++ 的解决方案使用类型列表,但它们要求所有类型都静态定义,这是我试图避免的。
这主要只是为了更好地学习 C++ 的思想练习,我确信我当前的实现不是很好的 C++。欢迎任何改进建议或尝试不同的想法。
我当前实现的主要问题是:
- 每个 mixin 类只知道其自身以及层次结构中低于其自身的类。我希望每个 mixin 类都能够返回具有不同底层类型的新 mixin。在下面的示例代码中,我希望
PrintOnce
能够有一个返回PrintTwice
对象。的方法。 > > - 这个想法的任何使用都需要有一个标头包含的顺序。一开始的所有样板代码都需要位于一个标头中,然后需要定义所有 mixin 类,最后可以定义 make_mixed 函数。目前,在 make_mixed 函数之后定义的任何 mixin 都会被忽略。
- 宏的实现和一般的hackyness。
对于篇幅,我深表歉意,但这是我能想到的最简单的例子。
感谢您的任何帮助。
#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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是一个没有宏的更干净的解决方案:
不幸的是,它仍然无法满足您让每个 mixin 类了解所有其他 mixin 类的要求。不过,我不确定这在编译时是否可能。
Here's a cleaner solution without macros:
Unfortunately, it still doesn't accomplish your requirement of having each mixin class being aware of all other mixin classes. I'm not sure if that's even possible at compile-time, though.