简体   繁体   English

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

[英]Unpacking variadic template parameters into initializer list

I am currently trying to implement a general initializer to reduce the size of our codebase. 我目前正在尝试实现一般的初始化程序来减少代码库的大小。 At one point however, my code looked like this: 但有一次,我的代码看起来像这样:

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

Which starts to be less elegant. 哪个开始不那么优雅。 From my understanding, variadic templates seems to be the way to solve this issue. 根据我的理解,可变参数模板似乎是解决此问题的方法。 But I don't understand how this can be applied to my situation. 但我不明白这是如何适用于我的情况。

I would prefer something like this: 我更喜欢这样的东西:

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

Any suggestion on how unpackAll() should be implemented? 关于如何实现unpackAll()的任何建议? Thanks. 谢谢。

auto device = new T{ allArguments };

just needs to be 只是需要

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

In T{ args... } args... will expand the parameter pack to arg0, arg1, ..., argn for you. T{ args... } args...会将参数包扩展为arg0, arg1, ..., argn

You can see this working with 你可以看到这个

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

Edit to add perfect forwarding version 编辑以添加完美的转发版本

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

My C++14 answer, as a minimal working example 我的C ++ 14回答,作为一个最小的工作示例

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

You need to edit this for your needs a bit, to your code structure that is. 你需要根据自己的需要编辑这个,这是你的代码结构。 But note that vector constructor takes initializer_list and that list is generated from parameter pack in that static foo method. 但请注意, vector构造函数采用initializer_list ,该列表是从静态foo方法中的参数包生成的。

Edit: In your case, as others noted, you can just directly forward your parameter pack to your call. 编辑:在您的情况下,正如其他人所说,您可以直接将参数包转发给您的电话。 My answer shows passing them to an initializer_list . 我的答案显示将它们传递给initializer_list

So in fact, you can just do 事实上,你可以做到

static std::vector<T> foo(Args&& ...args) {
    std::vector<T> res{std::forward<Args>(args)...};
    return res;
}

and those arguments will be implicitly converted to an initializer_list . 这些参数将被隐式转换为initializer_list I explicitly showed the construction of an initializer_list from a parameter pack. 我明确地从参数包中显示了initializer_list的构造。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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