如何为类型列表中的每个类型创建一个元素,并将其添加到C ++中的向量中?

时间:2015-02-27 11:29:42

标签: c++ templates boost-mpl boost-fusion typelist

在C ++中,我想为类型列表中指定的每种类型创建一个新元素(shared_ptr)(并将结果指针添加到向量)。在伪代码中,这应该类似于:

vector< shared_ptr< baseT > > v;
foreach(type T: <derivedT1, derivedT2, ..., derivedTn>)
{
    v.emplace_back(make_shared< T >());
}

使用stdboost(MPL,Fusion,?)是否有简明的解决方案?

一些研究:

  • 我发现了类似的东西 type visitor over typelist in c++。 不幸的是,我目前无法想象如何使用上面示例中的创建代码替换该帖子中的sizeof,以及如何封装所需的定义以简化使用。
  • 在boost MPL和Fusion中,我还没有找到一个合适的迭代算法,只能在一个类型上运行(没有那种类型的实例)。

2 个答案:

答案 0 :(得分:4)

[完全披露:我开发Hana]

我将使用Hana库进行回答,该库尚未加入Boost,但很快就会提交正式审核。 Hana在统一界面下融合了MPL和Fusion的功能。

#include <boost/hana.hpp>
#include <memory>
#include <vector>


struct baseT { };
struct derivedT1 : baseT { };
struct derivedT2 : baseT { };
struct derivedT3 : baseT { };

int main() {
    std::vector<std::shared_ptr<baseT>> v;
    auto types = hana::tuple_t<derivedT1, derivedT2, derivedT3>;
    hana::for_each(types, [&](auto t) {
        // decltype(t)::type is derivedTk
        using T = typename decltype(t)::type;
        v.emplace_back(std::make_shared<T>());
    });
}

答案 1 :(得分:1)

以下代码是否符合您的需求?

#include <iostream>
#include <memory>
#include <vector>

using namespace std;

#define TYPELIST1(t1) t1
#define TYPELIST2(t1, t2) std::pair<t1, t2>
#define TYPELIST3(t1, t2, t3) std::pair<t1, TYPELIST2(t2, t3)>
#define TYPELIST4(t1, t2, t3, t4) std::pair<t1, TYPELIST3(t2, t3, t4)>

template <typename T>
struct add_obj {
    template <typename Base>
    static void make(std::vector<std::shared_ptr<Base>>& v)
    {
        v.emplace_back(std::make_shared<T>());
    }
};

template <typename T1, typename T2>
struct add_obj<std::pair<T1, T2>> {
    template <typename Base>
    static void make(std::vector<std::shared_ptr<Base>>& v)
    {
        v.emplace_back(std::make_shared<T1>());
        add_obj<T2>::make(v);
    }
};

struct Obj { Obj(int n) : value(n) {} int value; };
struct Obj1 : Obj { Obj1() : Obj(1) {} };
struct Obj2 : Obj { Obj2() : Obj(2) {} };

int main()
{
    std::vector<shared_ptr<Obj>> v;
    add_obj<Obj1>::make(v);
    add_obj<TYPELIST3(Obj1, Obj2, Obj1)>::make(v);
    for (auto p : v) {
        std::cout << p->value << std::endl;
    }
}