【问题标题】:How to initialize a std::vector from variadic templates with different type each?如何从具有不同类型的可变参数模板初始化 std::vector?
【发布时间】:2022-01-16 12:10:00
【问题描述】:

我的主要问题是我正在尝试创建一个函数来初始化一个可以通过不同方式初始化的类的std::vector,所以我决定使用可变参数模板,但是,就像在这个例子中一样,确实如此不编译:

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

实际上,我想知道您是否想出一种更聪明的方法。

【问题讨论】:

    标签: c++ templates variadic-templates


    【解决方案1】:

    您需要将可变参数放在最后,并且可以使用折叠表达式来填充vec。你也可以做到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;
    }
    

    上面的函数可以简化为:

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

    如果你真的想要一个递归调用:

    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)...);
    }
    

    【讨论】:

    • 所以换句话说,我忘记写一种方法来停止递归,我必须切换最后两个参数。但是现在这个 c++17 fold-expressions 看起来更有吸引力
    • @JonnasKraft 是的,我认为折叠表达式非常好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-18
    相关资源
    最近更新 更多