简体   繁体   中英

How to initialize a std::vector from variadic templates with different type each?

My main problem is that i'm trying to create a function that initialize a std::vector of a class that can be initialized by different ways, so I decided to use variadic templates, but, like in this example, that does not compile:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

struct MyClass {
    MyClass(int v): value(v){}
    MyClass(string v): value(stoi(v)){}
    int value;
};

template<typename ...Args> vector<MyClass> mc_vector(const Args &...args);

int main()
{
    auto vec = mc_vector(1, "3", 5);
    for (auto &i : vec)
        cout << i.value << " ";
    cout << endl;
}

template<typename ...Args, typename T> void mc_vector_(vector<MyClass>& vec, const Args &...args, const T& t) {
    vec.emplace_back(t);
    mc_vector_(vec, args...);
}

template<typename ...Args> vector<MyClass> mc_vector(const Args &...args) {
    vector<MyClass> vec;
    vec.reserve(sizeof...(args));
    mc_vector_(vec, args...);
    return vec;
}

And actually, i would like to know if you image a smarter way of doing this.

You need to put the variadic argument last and you could use a fold-expression to populate vec . You could also make it do perfect forwarding :

#include <utility> // std::forward

template<typename... Args, typename T> 
void mc_vector_(vector<MyClass>& vec, T&& t, Args&&... args) {
    vec.emplace_back(std::forward<T>(t));
    (mc_vector_(vec, std::forward<Args>(args)), ...); // fold-expression
}

template<typename ...Args>
vector<MyClass> mc_vector(Args&&... args) {
    vector<MyClass> vec;
    vec.reserve(sizeof...(args));
    mc_vector_(vec, std::forward<Args>(args)...);
    return vec;
}

The top function could be simplified to:

template<typename... Args> 
void mc_vector_(vector<MyClass>& vec, Args&&... args) {
    (vec.emplace_back(std::forward<Args>(args)), ...); // fold-expression
}

If you really want a recursive call:

template<typename... Args, typename T> 
void mc_vector_(vector<MyClass>& vec, T&& t, Args&&... args) {
    vec.emplace_back(std::forward<T>(t));    
    if constexpr (sizeof...(Args) > 0) mc_vector_(vec, std::forward<Args>(args)...);
}

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