创建一个包含不同驱动器 class 元素的元组,其构造函数接收 int 类型,由其在元组中的索引确定

creates a tuple contains different drive class elements whose constructor received an int type, determined by its index in the tuple

我有一个基础 class,它的构造函数接收一个名为 id 的 int 类型,还有几个不同的派生 class,构造函数的形式与基础 class 相同。

现在我想制作一个包含每个元素的元组,其构造函数接收一个由其在该元组中的索引确定的 id。就像下面的哑函数所做的那样:

class Base(){
    Base(int id){}
}

class Derive1, Derived2...Derivedn : public Base(){
     Derive(int id):Base(id){}
}

auto make_derives_tuple()->decltype(...){
   //manually write each elements' index in the tuple seems too ugly and unnecessary
   return std::make_tuple(Derive1(0),Derived2(1),Derived3(2)...); 
}

如果派生的数量class是三个:

struct Base{
    Base(int id){
        id_=id;
    }
    int id_;
};

struct Derive:public Base{
    Derive(int id):Base(id){

    }
};


struct Derive2:public Base{
    Derive2(int id):Base(id){

    }
};

auto make_derive_tuple()->decltype (std::make_tuple(Derive(0),Derive2(1),Derive3(2))){
    //I want the int passed to the derived class's construor automatically generated according to it's position in the tuple
    return std::make_tuple(Derive(0),Derive2(1),Derive3(2));
}

但是在元组中手动写入每个元素的索引以传递给构造函数似乎太丑陋且没有必要。有什么优雅的方法可以实现这一目标吗?就像使用可变参数模板 class 或函数一样。

我没有看到一种优雅的方法来简单地迭代 类 作为 Derived1Derived2Derived3

但如果您可以模板化您的派生 类,则情况不同,添加模板索引,如下或以类似的方式

template <std::size_t>
struct Derived : public Base
 { Derived (int id) : Base{id} {} };

如果你也可以用C++14,可以用std::make_index_sequence/std::index_sequence如下

template <std::size_t ... Is>
auto make_helper (std::index_sequence<Is...> const &)
 { return std::make_tuple(Derived<Is+1u>{Is}...); }

template <std::size_t N>
auto make_derives_tuple ()
 { return make_helper(std::make_index_sequence<N>{}); }

下面是一个完整的编译示例

#include <tuple>
#include <utility>
#include <type_traits>

struct Base
 { Base (int) {} };

template <std::size_t>
struct Derived : public Base
 { Derived (int id) : Base{id} {} };

template <std::size_t ... Is>
auto make_helper (std::index_sequence<Is...> const &)
 { return std::make_tuple(Derived<Is+1u>{Is}...); }

template <std::size_t N>
auto make_derives_tuple ()
 { return make_helper(std::make_index_sequence<N>{}); }

int main()
 {
   auto t = make_derives_tuple<3u>();

   using T0 = decltype(t);
   using T1 = std::tuple<Derived<1u>, Derived<2u>, Derived<3u>>;

   static_assert( std::is_same<T0, T1>::value, "!" );
 }

如果您不能模板化(添加索引)派生 类,我能想象的最好的办法是将所需的派生 类 作为模板可变参数列表传递给 make_derived_tuple()

解变成

template <typename ... Ts, std::size_t ... Is>
auto make_helper (std::index_sequence<Is...> const &)
 { return std::make_tuple(Ts{Is}...); }

template <typename ... Ts>
auto make_derives_tuple ()
 { return make_helper<Ts...>(std::index_sequence_for<Ts...>{}); }

下面是一个完整的编译示例(我在其中重命名了 ABCD 派生的 类

#include <tuple>
#include <utility>
#include <type_traits>

struct Base
 { Base (int) {} };

struct A : public Base
 { A (int id) : Base{id} {} };

struct B : public Base
 { B (int id) : Base{id} {} };

struct C : public Base
 { C (int id) : Base{id} {} };

struct D : public Base
 { D (int id) : Base{id} {} };

template <typename ... Ts, std::size_t ... Is>
auto make_helper (std::index_sequence<Is...> const &)
 { return std::make_tuple(Ts{Is}...); }

template <typename ... Ts>
auto make_derives_tuple ()
 { return make_helper<Ts...>(std::index_sequence_for<Ts...>{}); }

int main()
 {
   auto t = make_derives_tuple<A, B, C, D>();

   using T0 = decltype(t);
   using T1 = std::tuple<A, B, C, D>;

   static_assert( std::is_same<T0, T1>::value, "!" );
 }