C++ 可变模板与多重遗传的结合

C++ 可变模板与多重遗传的结合,c++,c++14,C++,C++14,为了学习关于可变模板的一两件事,我偶然发现了这个问题(希望不是那么实际)。我有以下示例代码: #include <utility> #include <tuple> #include <iostream> template <typename... Args> auto args(Args&&... args) { return std::make_tuple(std::forward<Args>(args).

为了学习关于可变模板的一两件事,我偶然发现了这个问题(希望不是那么实际)。我有以下示例代码:

#include <utility>
#include <tuple>
#include <iostream>

template <typename... Args>
auto args(Args&&... args) {
    return std::make_tuple(std::forward<Args>(args)...);
}

template <class C, class TupleArgs, std::size_t... Indices>
C construct_class_unpacked_(TupleArgs&& args, std::index_sequence<Indices...>) {
    return C(std::get<Indices>(std::forward<TupleArgs>(args))...);
}

template <class C, typename TupleArgs>
C construct(TupleArgs&& args) {
    return construct_class_unpacked_<C>(std::forward<TupleArgs>(args), std::make_index_sequence<std::tuple_size<typename std::decay<TupleArgs>::type>::value>());
}

struct Root {
    Root(int l) : l_(l) {
    }

    protected:
        Root() : l_(-2) {}

    public:
        int l_;
};

struct A : public virtual Root {
    A(int i, float f) : i_(i), f_(f) {}

    int i_;
    float f_;
};

struct B : public virtual Root {
    B(int j, float g) : j_(j), g_(g) {}

    int j_;
    float g_;
};

struct C : public virtual Root {
    C() : x_(1), y_(3.1) {
    }

    int x_;
    float y_;
};

template <typename Base, typename... Bases>
struct S : public Bases... {
    template <typename Arg, typename... TupleArgs>
    S(Arg&& arg, TupleArgs&&... args) : Base(std::forward<Arg>(arg)), Bases(construct<Bases>(std::forward<TupleArgs>(args)))... {
    }
};

int main (int argc, char const* argv[]) {
    {
        S<Root, A, C, B> s(4, args(2, 3.1f), args(), args(3, 5.3f));
        std::cout << s.i_ << "\n";
        std::cout << s.f_ << "\n";
        std::cout << s.j_ << "\n";
        std::cout << s.g_ << "\n";
        std::cout << s.x_ << "\n";
        std::cout << s.y_ << "\n";
        std::cout << s.l_ << "\n";
    }
}
#包括
#包括
#包括
模板
自动参数(参数&&…参数){
返回std::make_tuple(std::forward(args)…);
}
模板
C构造\u类\u解包\u(TupleArgs&&args,std::index\u序列){
返回C(std::get(std::forward(args))…);
}
模板
C构造(TupleArgs和args){
返回构造类解包(std::forward(args),std::make_index_sequence());
}
结构根{
根(int l):l_u(l){
}
受保护的:
根()
公众:
国际劳工组织;
};
结构A:公共虚拟根目录{
A(inti,float f):i(i),f(f){}
国际组织;
浮动f_2;;
};
结构B:公共虚拟根目录{
B(intj,float g):j_j(j),g_g(g){}
int j_;
浮球;
};
结构C:公共虚拟根目录{
C():x_u1,y_3.1{
}
int x_2;;
浮动y_;
};
模板
结构S:公共基础。。。{
模板
S(Arg&&Arg,TupleArgs&&args):基(std::forward(Arg)),基(construct(std::forward(args)){
}
};
int main(int argc,char const*argv[]{
{
S(4,args(2,3.1f),args(),args(3,5.3f));

std::cout您可以使用helper类来执行单个基的初始化。 (它不是我最初称之为的包装器;它不使用聚合,而是使用继承。)

模板
用于元组扩展(元组&&)的自动生成索引序列
{
使用decayed_tuple=typename std::decayed::type;
返回std::make_index_sequence();
}
模板
结构解包器:T
{
模板
解包(元组和元组,std::index_序列)
:T(std::get(std::forward(tuple))…)
{}
模板
解包程序(元组和元组)
:解包器(标准::转发(元组),
制作索引序列,用于元组扩展(元组))
{}
};
模板
结构S:公共解包程序{
模板
S(Arg&&Arg,TupleArgs&&args)

:Base(std::forward

struct S:public Base…
为什么这不是从
Base
派生出来的?您可以将继承更改为递归的内容吗?例如,每个递归步骤作为基类的类型(作为第二个基类,递归的其余部分)。您可以包装每个基类,包装器执行解包。关于您的第一个问题:S通过其他类间接继承基类,因此我认为这是不必要的。关于递归继承,我尝试使用递归构造函数委托,这似乎是禁止的(理由充分).关于您最后的建议:这可能是个好主意;我正在尝试……
S
通过其他类间接继承Base”啊,如果
Base
是一个虚拟基类,那么这是可行的。否则,您可能无法从间接派生类初始化它。所有问题都可以通过添加一层间接寻址来解决,但间接寻址过多的问题除外。
template<class Tuple>
auto make_index_sequence_for_tuple_expansion(Tuple&&)
{
    using decayed_tuple = typename std::decay<Tuple>::type;
    return std::make_index_sequence<std::tuple_size<decayed_tuple>::value>();
}

template<class T>
struct unpacker : T
{
    template<class Tuple, std::size_t... Is>
    unpacker(Tuple&& tuple, std::index_sequence<Is...>)
        : T( std::get<Is>(std::forward<Tuple>(tuple))... )
    {}

    template<class Tuple>
    unpacker(Tuple&& tuple)
        : unpacker( std::forward<Tuple>(tuple),
                    make_index_sequence_for_tuple_expansion(tuple) )
    {}
};

template <typename Base, typename... Bases>
struct S : public unpacker<Bases>... {
    template <typename Arg, typename... TupleArgs>
    S(Arg&& arg, TupleArgs&&... args)
        : Base(std::forward<Arg>(arg))
        , unpacker<Bases>(std::forward<TupleArgs>(args))...
    {}
};