首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将元组传递给变量混合体类

将元组传递给变量混合体类
EN

Stack Overflow用户
提问于 2014-02-26 21:59:46
回答 1查看 535关注 0票数 4

我试图将一系列参数转发给两个不同的mixin类,如下所示:

代码语言:javascript
复制
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...) {
    }
};

Checker和Handler是Mixin类的两个不同的集合,每个类的需求不同,但所有成员的需求是共享的。我意识到,我不能在Tester中执行双变量结构(编译器无法推断在哪里拆分参数,以便将它们全部传递给Handler,而没有将它们传递给Checker),所以我在元组中传递Checker参数,在变量列表中传递Handler参数。问题是,Checker的构造函数负责将这些参数转发到其基础上。处理程序可以这样做,因为Handler的构造函数是一个可变的列表,但是Checker得到一个元组,但您不能这样做--每一个转发元组的元素都像前进一样,可以是一个可变参数列表。

如有任何建议,将不胜感激。谢谢。

附加

一种解决方案是:( a)将argc解压缩到Checker的各种构造函数中,或者( b)使Checker的构造器接受元组,然后以某种方式将该元组的每个元素转发给Checker的每个混合元素( Checkers... )。我意识到std::pair有一个技巧,可以将元组作为固定参数列表转发给它的类型,例如使用std::piecewise_construct类型标记的3参数std::vector构造函数来通知它进行解包,但我不知道如何在这里应用。我看了GCC 4.8.1的std::pairstd::piecewise_construct的实现,却搞不清楚。我读过一些关于模板元编程(例如,现代C++设计和C++模板元编程)的旧的C++11本书,但是现在我感到困惑,因为这里有一个标准,我试图避免Boost和Loki。

附加

必须至少符合GCC 4.7.2的要求。我所找到的基于std::pair的解决方案需要构造器继承,直到GCC 4.8.1 (在我的构建系统上不支持它)才可用。

附加

虽然GCC 4.6.3支持很好,但在4.7.2中添加了委托构造函数,所以我应该可以访问该语言特性。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-06 20:06:12

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

Davidbrcz的解决方案,正如他在上面的博客中所指出的,足以解决我的难题。解决方案相当复杂,因此我将为您指示他的页面,但基本思想是动态创建一个数字索引元组,àla std::maketuple(0,1,2,.)其中,元组包含需要枚举的元组的各个成员的每个索引。然后你就用:

代码语言:javascript
复制
M(std::forward<ArgM>(std::get<IdxM>(argm))...)

对于M作为C或H,在上面的示例和ArgM中,对M和IdxM的参数是相同大小的索引元组。因为列表的长度是相同的,所以列表被串联地滚动到参数中,并且元组被解压缩。

由于您希望将构建索引元组的复杂步骤隐藏为实现细节,因此需要使用Constructor委托,使公共构造函数接受两个元组,然后委托给私有构造函数,私有构造函数采用两个值元组和两个索引元组。GCC 4.7.2支持委托构造函数,但4.6.3不支持。

为了解决这个问题,您需要使4参数构造函数(值的2个元组,索引的2个元组)公开,然后我编写了一个宏来填充索引元组参数:

代码语言:javascript
复制
#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

然后在构造给定的测试器之后添加适当的宏,至少在GCC 4.6.3上还有一些人的时候,我努力让每个人都达到至少4.7.2和更好的4.8.1。:)

我希望我能对这个解决方案给予戴维布雷茨的信任,但至少这可能有助于那些面临类似问题的人在他们的具体情况下应用他的解决方案。主要是复制他的make_indices模板类来做实际的工作;剩下的是一个蛋糕走!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22054307

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档