简体   繁体   English

不同的可变参数模板扩展

[英]Different variadic template expansion

I want to prepare list of pairs of values from structure using variadic templates. 我想使用可变参数模板从结构中准备值对的列表。

#include <vector>

struct foo
{
    foo(int a, int b)
        : a(a), b(b) {}
    int a;
    int b;
};

struct Msg
{
    std::vector<int> valueArray;    
};

template<typename... Args>
Msg func(Args... args)
{
    Msg msg;
    msg.valueArray = { sizeof...(args), (args.a)..., (args.b)... };
    return msg;
}

int main() {
    Msg msg = func(foo{1,2}, foo{3,4}, foo{5,6});
}

Msg which func will return will have valueArray = [3, 1, 3, 5, 2, 4, 6] . 函数将返回的消息将具有valueArray = [3, 1, 3, 5, 2, 4, 6]

Is there any simple way to expand variadic paremeters in a way, where valueArray will look like valueArray = [3, 1, 2, 3, 4, 5, 6] ? 是否有任何简单的方法来扩展可变参数的方式,其中valueArray看起来像valueArray = [3, 1, 2, 3, 4, 5, 6]

The following is not as generic as I'd like to, but maybe it is sufficient for you: 以下内容并不像我想的那样通用,但也许对您来说已经足够了:

template<typename Arr, std::size_t... Is>
Msg func2( const Arr& arr, std::index_sequence<Is...> )
{
    Msg msg;
    msg.valueArray = {
        sizeof...(Is) / 2,
        ( ( Is % 2 == 0 ) ? std::get< Is / 2 >( arr ).a
                          : std::get< Is / 2 >( arr ).b )... };
    return msg;
}

template<typename... Args>
Msg func(Args... args)
{
    return func2( std::forward_as_tuple( args... ),
                  std::make_index_sequence< 2*sizeof...(Args) >() );
}

Live example 实例

Using C++14 features, a general solution can be obtained: 使用C ++ 14功能,可以获得一般解决方案:

struct Msg {
    std::vector<int> values;
};

template <std::size_t... indices, typename Tuple, typename OutputIt>
void copy(std::index_sequence<indices...>, Tuple&& t, OutputIt out) {
    (void)std::initializer_list<int> {
        (*out++ = std::get<indices>(std::forward<Tuple>(t)), 0)...
    };
}

template <typename Tuple, typename OutputIt>
void copy(Tuple&& t, OutputIt out) {
    copy(std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>{}>{},
         std::forward<Tuple>(t), out);
}

template <typename... Args>
Msg func(Args... args) {
    auto cat = std::tuple_cat(args...);
    Msg m{{sizeof...(args)}};
    copy(cat, std::back_inserter(m.values));
    return m;
}

// For demonstration:
template <typename... T>
auto foo(T&&... t) {return std::make_tuple(std::forward<T>(t)...);}

The usage is more flexible than before: 用法比以前更灵活:

Msg msg = func(foo(1,2,3), foo(4), foo(5,6,7));

Demo . 演示

You can define foo to be a (fixed sized) tuple as well, eg using foo = std::tuple<int, int>; 您也可以将foo定义为(固定大小)元组,例如using foo = std::tuple<int, int>; , then your above example compiles without the auxiliary function (after adjusting the braces, of course). ,然后你的上面的例子编译没有辅助功能(当然,在调整大括号后)。

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

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