2014-02-26 40 views
2

我想如下转发的一系列参数,以两种不同的mixin类:传递一个元组作为可变参数的混合类

template <typename... Checkers> 
class Checker : public Checkers... { 
public: 
    template<typename... Args> 
    Checker(Args&&... args) : Checkers(std::forward<Args>(args))... { } 
}; 

template <typename... Handlers> 
class Handler : public Handlers... { 
public: 
    template <typename... Args> 
    Handler(Args&&... args) : Handlers(std::forward<Args>(args))... { } 
}; 

template <typename C, typename H> 
class Tester : public C, H { 
public: 
    template <typename... ArgC, typename... ArgH> 
    Tester(std::tuple<ArgC...>&& argc, ArgH&&... argh) : C(argc), H(argh...) { 
    } 
}; 

检查和处理程序是密新课程针对不同需求的两个不同的集合每个成员都共享需求。我意识到我不能在Tester中做一个双变量构造(编译器不能推断出在哪里分割参数,所以把它们全部传递给Handler而没有传递给Checker),所以我传递了Tuple中的Checker参数和Handler参数一个可变名单。问题是,Checker的构造函数负责将这些参数转发给它的基地。 Handler可以这样做,因为Handler的构造函数是一个可变参数列表,但Checker获取一个元组,但是不能为每个元素转发一个元组,如向前可以包含可变参数列表。

任何意见将不胜感激。谢谢。

附加

的溶液。将或者a)解压argcChecker的可变参数的构造或b)使Checker的构造采取一个元组,然后以某种方式转发该元组中的每个元素的每一个Checker的mixin碱基,Checkers...。我知道std::pair有一个将元组作为固定参数列表转发给它的类型的技巧,例如使用std::piecewise_construct类型标记的3参数std::vector构造函数通知它进行解压缩,但我不明白这可能是什么在这里应用。我查看了std::piecewise_construct的GCC 4.8.1的std::pair的执行情况,但无法弄清楚。我阅读了一些关于模板元编程的旧版C++ 11之前的书籍(例如,Modern C++ DesignC++ Template Metaprogramming),但是现在我不知道这里有标准,试图避免Boost和Loki。

附加

必须符合至少GCC 4.7.2。我找到的基于std::pair的解决方案需要构造函数继承,直到GCC 4.8.1才生效,这在我的构建系统上不受支持。

附加

虽然GCC 4.6.3支持将是很好的,委托构造在4.7.2中加入所以我应该有机会获得该语言功能。在他的博客上面指定

+1

可能[this SO question](http://stackoverflow.com/questions/10766112/c11-i-can-go-from-multiple-args-to-tuple-but-can-i-go-from双倍)可以提供帮助。 – maverik

+0

我还不确定,因为问题是调用一个基本的构造函数,这是一个有限的调用约定,所以我的第一读书是行不通的,但让我仔细考虑它,看看我是否可以扭曲它来匹配我正在寻找。 – TimeHorse

+0

你可以模拟'std :: pair'的“分段”构造函数。 –

回答

2

http://cpptruths.blogspot.fr/2012/06/perfect-forwarding-of-parameter-groups.html

Davidbrcz的解决方案是足以解决我的难题。解决方案相当复杂,所以我会引导你到他的页面,但基本的想法是即时创建一个数字索引元组,àla std :: maketuple(0,1,2,... )其中元组包含您需要枚举的元组的各个成员的每个索引。然后,你只需使用:

M(std::forward<ArgM>(std::get<IdxM>(argm))...) 

对于M为无论是C或H在上述的例子和ArgM的参数M和IdxM指数的大小相等的元组。由于列表长度相同,因此列表将逐个展开到参数中,并将元组解包。

这个限制是因为你需要将构建索引元组的复杂步骤作为实现细节隐藏起来,所以需要使用构造函数委派,这样公共构造函数就接受了2个元组,然后委托给私有构造函数2个值元组和2个索引元组。 GCC 4.7.2支持Delegated Constructors,但4.6.3不支持。

要解决这个问题,你需要做的4个参数的构造函数(2元组的值,2元组指数)公共,然后我写了一个宏来填写索引记录参数:

#if __GNUC__ < 4 || __GNUC_MINOR__ <= 6 
#define ZEROPARAM , detail::make_indices<>::type() 
#define ONEPARAM , detail::make_indices<int>::type() 
#define TWOPARAM , detail::make_indices<int, int>::type() 
#define THREEPARAM , detail::make_indices<int, int, int>::type() 
#define FOURPARAM , detail::make_indices<int, int, int, int>::type() 
#define FIVEPARAM , detail::make_indices<int, int, int, int, int>::type() 
#define SIXPARAM , detail::make_indices<int, int, int, int, int, int>::type() 
#define SEVENPARAM , detail::make_indices<int, int, int, int, int, int, int>::type() 
#define EIGHTPARAM , detail::make_indices<int, int, int, int, int, int, int, int>::type() 
#define NINEPARAM , detail::make_indices<int, int, int, int, int, int, int, int, int>::type() 
#define TENPARAM , detail::make_indices<int, int, int, int, int, int, int, int, int, int>::type() 
#else // __GNUC__ < 4 || __GNUC_MINOR__ <= 6 
#define ZEROPARAM 
#define ONEPARAM 
#define TWOPARAM 
#define THREEPARAM 
#define FOURPARAM 
#define FIVEPARAM 
#define SIXPARAM 
#define SEVENPARAM 
#define EIGHTPARAM 
#define NINEPARAM 
#define TENPARAM 
#endif // __GNUC__ < 4 || __GNUC_MINOR__ <= 6 

然后在给定Tester的构建之后添加适当的宏,至少在GCC 4.6.3上仍然有人参与时,而我努力让每个人都至少达到4.7.2,最好是4.8.1。 :)

我希望我可以给解决方案的Davidbrcz信贷,但至少这可能有助于面临类似问题的人在他们的具体情况下应用他的解决方案。主要的是复制他的make_indices模板类来完成实际的工作;剩下的就是蛋糕散步!

相关问题