简体   繁体   中英

How to create an element for each type in a typelist and add it to a vector in C++?

In C++, I 'd like to create a new element (shared_ptr) for each type specified in a typelist (and add the resulting pointers to a vector). In pseudo code, this should look similar to this:

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

Is there a concise solution for this using std or boost (MPL, Fusion, ?)?

Some Research:

  • I found something similar in type visitor over typelist in c++ . Unfortunately, I currently can't conceive a way how to replace the sizeof from that post with the creation code from the example above and how to encapsulate the required definitions for concise usage.
  • In boost MPL and Fusion, I could not yet find a suitable iteration algorithm operating only on a type (without an instance of that type).

[Full disclosure: I develop Hana]

I'll answer using the Hana library, which is not yet in Boost but will be proposed for formal review soon. Hana merges the functionality of MPL and Fusion under a unified interface.

#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>());
    });
}

Does something like the following code meet your needs?

#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;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM