将可变参数模板参数解压缩到初始化程序列表中

时间:2018-07-20 20:13:30

标签: c++ c++11 templates variadic-templates

我目前正在尝试实现通用的初始化程序,以减少代码库的大小。但是,在某一时刻,我的代码看起来像这样:

template<typename T, typename Arg1, typename Arg2>
T* ManageDevice(Arg1 arg1, Arg2 arg2)
{
    auto device = new T{ arg1, arg2 };
    // More operations on device
    return device;
}

template<typename T, typename Arg1, typename Arg2, typename Arg3>
T* ManageDevice(Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
    auto device = new T{ arg1, arg2, arg3 };
    // More operations on device
    return device;
}

template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
T* ManageDevice(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
{
    auto device = new T{ arg1, arg2, arg3, arg4 };
    // More operations on device
    return device;
}

哪个开始不太优雅。据我了解,可变参数模板似乎是解决此问题的方法。但是我不知道如何将其应用于我的情况。

我希望这样:

T* ManageDevice(Args... args)
{
    // The function I want
    // Unpack as a std::initializer_list
    auto allArguments = unpackAll(); 

    auto device = new T{ allArguments };
    // More operations on device
    return device;
}

关于应如何实现unpackAll()的任何建议? 谢谢。

2 个答案:

答案 0 :(得分:3)

auto device = new T{ allArguments };

只是需要

auto device = new T{ args... };

T{ args... }中,args...会为您扩展参数包到arg0, arg1, ..., argn

您可以看到它与之配合使用

template <typename... Args>
std::vector<int> make_vector(Args... args)
{
    return {args...};
}

int main()
{
    auto foo = make_vector(1,2,3,4);
    for (auto e : foo)
        std::cout << e << " ";
}

编辑以添加完善的转发版本

template <typename... Args>
std::vector<int> make_vector(Args&&... args)
{
    return {std::forward<Args>(args)...};
}

答案 1 :(得分:0)

我的C ++ 14答案,作为最小的工作示例

$(".child").next().next()...

您需要根据需要对代码结构进行一些编辑。但是请注意,#include <initializer_list> #include <utility> #include <vector> #include <type_traits> #include <iostream> struct example { template <typename ...Args, typename T = std::common_type_t<Args...>> static std::vector<T> foo(Args&& ...args) { std::initializer_list<T> li{std::forward<Args>(args)...}; std::vector<T> res{li}; return res; } }; int main() { std::vector<int> v1 = example::foo(1,2,3,4); for(const auto& elem: v1) std::cout << elem << " "; std::cout << "\n"; } 构造函数采用vector,并且该列表是通过该静态initializer_list方法的参数包生成的。

编辑:就您的情况而言,就像其他人指出的那样,您可以直接将参数包转发给您的呼叫。我的回答显示将它们传递到foo

实际上,您可以这样做

initializer_list

,这些参数将隐式转换为static std::vector<T> foo(Args&& ...args) { std::vector<T> res{std::forward<Args>(args)...}; return res; } 。我明确显示了参数包中initializer_list的构造。