【发布时间】:2012-11-05 08:02:10
【问题描述】:
我希望能够做到这一点:
template<typename Mix>
struct A {
A(int i) { }
};
template<typename Mix>
struct B {
B() { }
B(const char*) { }
};
template<template<typename> class... Mixins>
struct Mix : Mixins<Mix<Mixins...>>... {
// This works, but forces constructors to take tuples
template<typename... Packs>
Mix(Packs... packs) : Packs::Type(packs.constructorArgs)... { }
};
template<template<typename> class MixinType, typename... Args>
struct ArgPack {
typedef MixinType Type; // pretend this is actually a template alias
tuple<Args...> constructorArgs;
ArgPack(Args... args) : constructorArgs(args...) { }
}
template<typename... Args>
ArgPack<A, Args...> A_(Args... args) {
return ArgPack<A, Args...>(args...);
}
template<typename... Args>
ArgPack<B, Args...> B_(Args... args) {
return ArgPack<B, Args...>(args...);
}
Mix<A, B> m(); // error, A has no default constructor
Mix<A, B> n(A_(1)); // A(int), B()
Mix<A, B> n(A_(1), B_("hello"); // A(int), B(const char*)
我如何在这里填写/*神秘代码*/来做我想做的事,提供一个很好的接口来调用一些mixins的构造函数?我有一个解决方案,它通过使所有非空构造实际上采用一个 args 元组,然后重载计算出要调用哪个,但我想通过让他们编写构造函数 A(元组)来避免约束 mixin 作者,而不仅仅是 A(int, int)。
谢谢!
【问题讨论】:
-
你的例子的问题是你一直在使用单元素元组,所以很难知道你到底在追求什么行为。如果您的目标是将元组扩展为
Base的单独构造函数参数,我认为这是不可能的。为什么不采用可变参数包而不是元组作为构造函数参数? -
呃,是的,你当然是对的。我会考虑一下,并用一个反映我实际意图的例子来修改这个问题。
-
代码现在更恶心 100% :)
-
struct Mix : Mixins<Mix<Mixins...>>...这一行似乎暗示着无限的递归。有关使用构造函数委托的高度复杂的 mixin 的示例,请查看我的 C++11 预处理器项目 code.google.com/p/c-plus/source/browse/src — 从 framework.h 开始。如果您可以消除对递归的渴望,转而使用更简单的 CRTP,事情会容易得多。 -
其实,它工作得很好。我在一个大型项目中使用这种风格的 mixin 已经有一段时间了,它可以编写非常优雅的代码。这是类固醇上的 CRTP :) 唯一的问题是我没有调用 mixin 构造函数的好方法:(
标签: c++ templates c++11 variadic-templates