我正在写一些代码,我有一个类可以接受mixins作为可变参数模板参数。但是,我还需要mixins才能通过CRTP习惯用法访问基类。这是一个最不能满足我想要的最小例子:
template <template <class> class... Mixins>
class Foo : Mixins<Foo<Mixins...>>... {};
但是,我可能传递给Foo
的mixin通常会有几个模板参数,如下所示:
template <class Derived, class Type1, class Type2>
class Bar
{
Derived& operator()()
{
return static_cast<Derived&>(*this);
}
};
如何更改Foo
以便我可以从多个基类继承它,我控制每个基类接受的模板参数?如果我递交Foo
模板模板参数列表以及传递给它们的参数列表,那么我不知道如何将每个模板模板参数与其参数相关联。到目前为止,我想到了这样的事情,但我不知道如何继续下去。
template <template <class...> class T,
template <class...> class... Ts>
class Foo : /* How do I retrieve the arguments? */
答案 0 :(得分:4)
我不太确定我是否明白这个问题,所以请让我改一下,以便我们能够从正确的方向开始。
在典型的CRTP用例中,您需要将派生类型线程化到基类,同时将其他模板参数传递给各种基类。
也就是说,典型的基类是:
template <typename Derived, typename X, typename Y>
struct SomeBase {
};
您需要创建自己的类型,以便控制X
和Y
,同时传递完整的Derived
类。
我想我会使用apply
技巧从Derived
类的参数列表中提供的适配器动态生成基类。
template <typename Derived, typename X, typename Y>
struct SomeBase {};
template <typename X, typename Y>
struct SomeBaseFactory {
template <typename Derived>
struct apply { typedef SomeBase<Derived, X, Y> type; };
};
// Generic application
template <typename Fac, typename Derived>
struct apply {
typedef typename Fac::template apply<Derived>::type type;
};
然后,您将创建类型:
typedef MyFoo< SomeBaseFactory<int, float> > SuperFoo;
Foo
定义为:
template <typename... Args>
struct Foo: apply<Args, Foo<Args...>>::type... {
};
仅仅因为我在模板中如此深入地跋涉已经有一段时间了I checked it worked。
当然,Factory
本身并不是特定于给定类型的特定类型,因此我们可以重用您尝试过的包装器方法:
template <template <typename...> class M, typename... Args>
struct Factory {
template <typename Derived>
struct apply { typedef M<Derived, Args...> type; };
};
是的,it works too。
答案 1 :(得分:2)
如果我正确理解您的问题,您应该创建模板别名,将每个mixin减少为单个模板参数。
template <typename Derived>
using BarIntFloat = Bar<Derived, Int, Float>;
template <typename Derived>
using BazQux = Baz<Derived, Qux>;
typedef Foo<BarIntFloat, BazQux> MyFoo;
答案 2 :(得分:0)
这是我提出的解决方案。可能有更优雅的方式来做到这一点,但我想不出任何。需要注意的是,所有使用的mixin都需要首先嵌套在wrapper
结构中,以及它们各自的参数。
template <template <class...> class Mixin, class... Args>
struct wrapper
{
typedef Mixin<Args...> type;
};
template <class... Args>
struct test
{
};
template <class Arg, class... Args>
struct test<Arg, Args...> : Arg::type, test<Args...>
{
};
template <class T>
class mixin1 {};
template <class T1, class T2>
class mixin2 {};
template <class T1, class T2, class T3>
class mixin3 {};
int main()
{
test<wrapper<mixin1, int>, wrapper<mixin2, int, float>> foo;
return 0;
}
答案 3 :(得分:0)
@空隙指针
这是可变参数模板的基本遗漏。用户无法从T ...获得第i个类型,或从值获得第i个值...
以下是来自Andrei Alexandrescu 2012年本土讲座的a link:
template <typename... Ts>
void fun(const Ts&... vs) {}
•Ts不是一种类型; vs不是一个值!
typedef Ts MyList; // error!
Ts var; // error!
auto copy = vs; // error!
所以Ts / vs应该是某种元组。