C++11下std::apply等效实现及RPC参数顺序与成员函数适配问题
解决RPC参数序列化/反序列化顺序问题及C++11版std::apply实现
一、修复参数顺序反转问题
参数包展开的求值顺序在C++11中未标准化,这会导致不同编译器下参数读取顺序不一致。核心解决思路是让序列化、反序列化全程严格遵循从左到右的固定顺序,彻底摆脱对编译器实现的依赖。
序列化端:强制左到右执行
初始化列表的求值顺序是C++标准明确定义的左到右,你可以用数组初始化的方式强化这一逻辑,避免参数包展开的乱序风险:
template<typename... Args> void Serialize(Args&&... args) { // 用数组初始化强制每个Push按左到右顺序执行 using swallow = int[]; (void)swallow{0, (Push(std::forward<Args>(args)), 0)...}; }
反序列化端:用索引序列固定参数顺序
反序列化时,将取出的参数存入std::tuple,后续通过索引序列按序列化顺序提取参数,确保传递给目标函数时顺序完全匹配。
二、C++11下实现支持成员函数的std::apply替代
std::apply的核心是将元组元素按顺序传递给函数/成员函数,在C++11中可通过手动实现索引序列来完成,同时兼容普通函数和成员函数:
1. 基础索引序列实现
先模拟C++14的std::index_sequence和std::make_index_sequence:
template<std::size_t... Ints> struct index_sequence {}; template<std::size_t N, std::size_t... Ints> struct make_index_sequence_impl : make_index_sequence_impl<N-1, N-1, Ints...> {}; template<std::size_t... Ints> struct make_index_sequence_impl<0, Ints...> : index_sequence<Ints...> {}; template<std::size_t N> using make_index_sequence = typename make_index_sequence_impl<N>::type;
2. 普通函数的apply实现
template<typename Func, typename Tuple, std::size_t... Indices> auto apply_impl(Func&& func, Tuple&& tuple, index_sequence<Indices...>) -> decltype(std::forward<Func>(func)(std::get<Indices>(std::forward<Tuple>(tuple))...)) { return std::forward<Func>(func)(std::get<Indices>(std::forward<Tuple>(tuple))...); } template<typename Func, typename Tuple> auto apply(Func&& func, Tuple&& tuple) -> decltype(apply_impl(std::forward<Func>(func), std::forward<Tuple>(tuple), make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{})) { return apply_impl(std::forward<Func>(func), std::forward<Tuple>(tuple), make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{}); }
3. 成员函数的apply实现
区分非const和const成员函数,支持对象指针或引用:
// 非const成员函数版本 template<typename MemFunc, typename Obj, typename Tuple, std::size_t... Indices> auto apply_mem_impl(MemFunc mem_func, Obj&& obj, Tuple&& tuple, index_sequence<Indices...>) -> decltype((std::forward<Obj>(obj).*mem_func)(std::get<Indices>(std::forward<Tuple>(tuple))...)) { return (std::forward<Obj>(obj).*mem_func)(std::get<Indices>(std::forward<Tuple>(tuple))...); } template<typename MemFunc, typename Obj, typename Tuple> auto apply_mem(MemFunc mem_func, Obj&& obj, Tuple&& tuple) -> decltype(apply_mem_impl(mem_func, std::forward<Obj>(obj), std::forward<Tuple>(tuple), make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{})) { return apply_mem_impl(mem_func, std::forward<Obj>(obj), std::forward<Tuple>(tuple), make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{}); } // const成员函数版本 template<typename MemFunc, typename Obj, typename Tuple, std::size_t... Indices> auto apply_mem_const_impl(MemFunc mem_func, const Obj& obj, Tuple&& tuple, index_sequence<Indices...>) -> decltype((obj.*mem_func)(std::get<Indices>(std::forward<Tuple>(tuple))...)) { return (obj.*mem_func)(std::get<Indices>(std::forward<Tuple>(tuple))...); } template<typename MemFunc, typename Obj, typename Tuple> auto apply_mem_const(MemFunc mem_func, const Obj& obj, Tuple&& tuple) -> decltype(apply_mem_const_impl(mem_func, obj, std::forward<Tuple>(tuple), make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{})) { return apply_mem_const_impl(mem_func, obj, std::forward<Tuple>(tuple), make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{}); }
三、整合RPC调用逻辑
- 序列化:用数组初始化方式左到右推入参数,确保顺序固定。
- 反序列化:将取出的参数存入
std::tuple,通过apply或apply_mem函数,借助索引序列严格按序列化顺序传递给目标函数,完全消除编译器依赖的顺序问题。
示例调用:
// 普通函数调用 void foo(int a, std::string b) { /* 业务逻辑 */ } std::tuple<int, std::string> args = {123, "test"}; apply(foo, args); // 非const成员函数调用 struct Bar { void func(double x) { /* 业务逻辑 */ } }; Bar bar; std::tuple<double> mem_args = {3.14}; apply_mem(&Bar::func, bar, mem_args); // const成员函数调用 struct Baz { std::string get_name() const { return "baz"; } }; const Baz baz; std::tuple<> empty_args; std::string name = apply_mem_const(&Baz::get_name, baz, empty_args);
内容的提问来源于stack exchange,提问作者Russ Schultz
相关产品推荐
相关产品推荐

