C++ 如何调用所有可变继承类的函数?
我非常感谢任何一位模板大师在这方面的帮助。我将CRTP用于mixin类,希望能够将参数传递给派生类的函数,并让它调用所有mixin的继承函数,并转发适当数量的参数。例如:C++ 如何调用所有可变继承类的函数?,c++,variadic-templates,multiple-inheritance,variadic-functions,fold,C++,Variadic Templates,Multiple Inheritance,Variadic Functions,Fold,我非常感谢任何一位模板大师在这方面的帮助。我将CRTP用于mixin类,希望能够将参数传递给派生类的函数,并让它调用所有mixin的继承函数,并转发适当数量的参数。例如: template struct Mixin1{void Initialize(int,double);}; 模板结构Mixin2{void Initialize();}; 模板结构Mixin3{void Initialize(double);}; 模板 结构实体:公共组件。。。 { 模板 无效初始化(常量T&,参数&&…参数)
template struct Mixin1{void Initialize(int,double);};
模板结构Mixin2{void Initialize();};
模板结构Mixin3{void Initialize(double);};
模板
结构实体:公共组件。。。
{
模板
无效初始化(常量T&,参数&&…参数){
(类型::初始化(转发(args)),…);
}
}
并使用类似于:
entity.Initialize(42,42.0,42.0);
是否可以将适当数量的参数传递给每个参数?上面的代码当然不起作用,但我的想法是尝试用每个参数的类型实例化一个空模板的方法(即variadv1;variadv2;variadv3;
)并将包含所有这些参数的变量与参数一起传递到函数中,但我似乎不知道如何正确分割参数
是否可以将适当数量的参数传递给每个参数
据我所知,这不是一种简单的方式
当然这是可能的,计算每个方法的参数,并使用递归(也是递归变量lambdas)和SFINAE
我开发了以下示例只是因为我喜欢模板元编程;但我是第一个说这是一场疯狂的噩梦的人
#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);
}
#包括
#包括
#包括
模板
constexpr std::size\u t numArgs(R(t::*)(As…)
{return sizeof…(As);}
模板
结构Mixin1
{
无效初始化(整数i,双d)
{std::cout只是为了确保…给定实体实体;
,从调用实体。初始化(1,2.0,3.0);
您想要的是从混合1
调用初始化(1,2.0)
,初始化()
从混合2
和初始化(3.0)
来自Mixin3
?应该可以想出一些混乱的TMP解决方案,但是一旦有人使mixin类的Initialize
方法重载或创建模板,它就会崩溃。相反,您应该让Entity::Initialize
获取参数元组列表,从每个元组到相应的mixin的Initialize
方法。是的@max66这是预期的行为。@Brian一个混乱的TMP解决方案实际上对我来说没问题,可以安全地假设函数将被模板化或重载。主要的需要是使用具有完美转发和不复制的函数。如果我没有错用元组w我至少需要复制一次否?顺便说一句,我认为TMP解决方案无论如何都会创建元组(对于元组,您可能需要tuple
,以避免额外的复制).Hot diggity他成功了!我几乎想知道是否有更简洁的方法来使用折叠表达式?我会继续玩它,看看是否找不到方法。谢谢!幸运的是,这只是一个个人项目,因此没有人会看到它。顺便说一句,它在IH1中缺少了一个自动后(&after)lambda@GarinStrader - “IH1 lambda中缺少了一个&after自动”-D'oh!你是对的;更正了;谢谢。g++和clangg++都没有发出这一信号。只是好奇(所以我没有花太多时间旋转车轮),似乎不可能为构造函数实现这一点?事实上,我并不需要它,但我仍然很好奇这是否可能。非常确定这不是,实际上没有一种方法可以使用此结构调用初始值设定项列表中的每个构造函数