我想使用可变参数模板从结构中准备值对的列表。
#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});
}
func将返回的消息将为valueArray = [3, 1, 3, 5, 2, 4, 6]
。
有没有简单的方法来扩展可变参数的方式,其中valueArray看起来像valueArray = [3, 1, 2, 3, 4, 5, 6]
?
答案 0 :(得分:4)
以下内容并不像我想的那样通用,但也许对您来说已经足够了:
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) >() );
}
答案 1 :(得分:3)
使用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)...);}
使用比以前更灵活:
Msg msg = func(foo(1,2,3), foo(4), foo(5,6,7));
您也可以将foo
定义为(固定大小)元组,例如using foo = std::tuple<int, int>;
,那么上面的例子在没有辅助函数的情况下进行编译(当然,在调整大括号之后)。