[英]How can I call a function of all variadically inherited classes?
I'd be grateful to any template gurus out there for some help on this one.我会感谢任何模板专家在此方面提供帮助。 I'm using CRTP for a mixin class and would like to be able to pass arguments to a function of the derived class and have it call the inherited functions of all mixins and forward the appropriate number of arguments.
我正在将 CRTP 用于 mixin 类,并希望能够将参数传递给派生类的函数,并让它调用所有 mixin 的继承函数并转发适当数量的参数。 Eg:
例如:
template<Host> struct Mixin1 { void Initialize(int, double); };
template<Host> struct Mixin2 { void Initialize(); };
template<Host> struct Mixin3 { void Initialize(double); };
template <template<class> class... Components>
struct Entity : public Components<Entity<Components...>>...
{
template<template<class> class ...Types, template<template<typename>typename...> class T, class... Args>
void Initialize(const T<Types...>&, Args&&... args) {
(Types<Entity<Types>>::Initialize(forward<Types>(args)),...);
}
}
And use like:并使用如下:
entity.Initialize(42,42.0,42.0);
Is it possible to pass the appropriate number of arguments to each?是否可以将适当数量的参数传递给每个参数? The code above of course doesn't work but my idea was to try the method of instantiating an empty template with the types of each of the arguments (ie
Variad<int, double> v1; Variad<> v2; Variad<double> v3;
) and pass a variad containing all those into the function along with the arguments but I can't seem to figure out how to split the arguments correctly.上面的代码当然不起作用,但我的想法是尝试使用每个参数的类型实例化一个空模板的方法(即
Variad<int, double> v1; Variad<> v2; Variad<double> v3;
) 并将包含所有这些的变量与参数一起传递到函数中,但我似乎无法弄清楚如何正确拆分参数。
Is it possible to pass the appropriate number of arguments to each?
是否可以将适当数量的参数传递给每个参数?
Not in a simple way, as far I can understand.不是以一种简单的方式,据我所知。
Surely it's possible, counting argument of every method and using recursion (also recursive variadic lambdas) and SFINAE.当然有可能,计算每个方法的参数并使用递归(也是递归可变参数 lambdas)和 SFINAE。
I've developed the following example just because I love template metaprogramming;我开发了以下示例只是因为我喜欢模板元编程; but I'm the first to say that it's a delirious nightmare.
但我是第一个说这是一场神志不清的噩梦的人。
#include <utility>
#include <iostream>
#include <type_traits>
template <typename R, typename T, typename ... As>
constexpr std::size_t numArgs (R(T::*)(As...))
{ return sizeof...(As); }
template <typename>
struct Mixin1
{
void Initialize (int i, double d)
{ std::cout << "I1: " << i << ", " << d << std::endl; }
};
template <typename>
struct Mixin2
{
void Initialize ()
{ std::cout << "I2:" << std::endl; }
};
template <typename>
struct Mixin3
{
void Initialize (double d)
{ std::cout << "I3: " << d << std::endl; }
};
template <template <typename> class ... Cs>
struct Entity : public Cs<Entity<Cs...>>...
{
template <std::size_t Pos, typename ... Ts,
typename F, std::size_t I0, std::size_t ... Is,
typename ... As>
std::enable_if_t<(Pos == I0)>
Ih2 (F const & f, std::index_sequence<I0, Is...> const &,
As && ... as)
{
f(); // exec an Initialize();
Ih1<Ts...>(std::index_sequence<Is...>{}, std::forward<As>(as)...);
}
template <std::size_t Pos, typename ... Ts,
typename F, std::size_t I0, std::size_t ... Is,
typename A0, typename ... As>
std::enable_if_t<(Pos < I0)>
Ih2 (F const & f, std::index_sequence<I0, Is...> const & is,
A0 && a0, As && ... as)
{ Ih2<Pos+1u, Ts...>
([&a0, &f](auto && ... as2) { f(std::forward<A0>(a0),
std::forward<decltype(as2)>(as2)...); },
is, std::forward<As>(as)...); }
template <int = 0>
void Ih1 (std::index_sequence<> const &)
{ }
template <typename T0, typename ... Ts,
std::size_t ... Is, typename ... As>
void Ih1 (std::index_sequence<Is...> const & is, As && ... as)
{ Ih2<0u, Ts...>
([this](auto && ... as2)
{ T0::Initialize(std::forward<decltype(as2)>(as2)...); },
is, std::forward<As>(as)...); }
template <typename ... As>
void Initialize (As && ... args)
{ Ih1<Cs<Entity<Cs...>>...>
(std::index_sequence<numArgs(&Cs<Entity<Cs...>>::Initialize)...>{},
std::forward<As>(args)...); }
};
int main ()
{
Entity<Mixin1, Mixin2, Mixin3> entity;
entity.Initialize(1, 2.0, 3.0);
}
As said in a comment, this solution doesn't works in case of overloading, or template, for Initialize()
in the single Components
.正如评论中所说,此解决方案在重载或模板的情况下不适用于单个
Components
中的Initialize()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.