如何利用带可变参数的C++模板实现结构体成员的自动批量赋值?
实现结构体成员自动赋值的C++模板方案
当然可以用C++模板来实现这种结构体成员的自动赋值!针对你的场景,我们可以通过模板配合成员指针映射的方式,实现编译期的批量赋值,既减少重复代码,又保证和手动赋值一样的效率。下面提供两种实用的方案:
方案一:通用模板+成员指针映射(灵活适配不同结构体)
这个方案的核心是定义通用的赋值模板,然后通过成员指针对来指定源结构体和目标结构体的成员映射关系,适用于成员名称不完全一致的场景(比如你的例子里absolute_altidue_m和absolute_altitude_m,即便存在笔误,模板依然能处理)。
#include <utility> // 单个成员的赋值工具函数 template <typename SourceT, typename DestT> void assign_single_member(DestT& dest, const SourceT& src, auto dest_member_ptr, auto src_member_ptr) { dest.*dest_member_ptr = src.*src_member_ptr; } // 批量赋值的模板函数,利用C++17折叠表达式遍历所有成员对 template <typename SourceT, typename DestT, typename... MemberPairs> void assign_members(DestT& dest, const SourceT& src, MemberPairs&&... pairs) { (assign_single_member(dest, src, std::get<0>(pairs), std::get<1>(pairs)), ...); } // 针对你的两个结构体,特化赋值逻辑 template <> void assign_members<mavsdk::Telemetry::Position, mavsdk_interface::gpsPos>( mavsdk_interface::gpsPos& dest, const mavsdk::Telemetry::Position& src) { // 定义源和目标的成员映射对:(目标成员指针, 源成员指针) assign_members(dest, src, std::make_pair(&mavsdk_interface::gpsPos::latitude_deg, &mavsdk::Telemetry::Position::latitude_deg), std::make_pair(&mavsdk_interface::gpsPos::longitude_deg, &mavsdk::Telemetry::Position::longitude_deg), std::make_pair(&mavsdk_interface::gpsPos::absolute_altidue_m, &mavsdk::Telemetry::Position::absolute_altitude_m), std::make_pair(&mavsdk_interface::gpsPos::relative_altitude_m, &mavsdk::Telemetry::Position::relative_altitude_m) ); }
使用方式
在你的订阅回调里,直接调用模板函数即可完成自动赋值:
void subcribePosition(ros::Publisher& posGPS_pub, mavsdk::Telemetry & telemetry){ telemetry.subscribe_position([&](mavsdk::Telemetry::Position pos){ mavsdk_interface::gpsPos msg; // 一键完成所有成员赋值 assign_members(msg, pos); posGPS_pub.publish(msg); }); }
方案二:简化版(成员名称一致时)
如果你的两个结构体成员名称完全一致(比如修正笔误后absolute_altitude_m匹配),可以用宏配合模板来进一步简化代码:
// 宏定义单个成员赋值 #define ASSIGN_MEMBER(dest, src, member) dest.member = src.member // 针对特定结构体的赋值模板 template <> void assign_members<mavsdk::Telemetry::Position, mavsdk_interface::gpsPos>( mavsdk_interface::gpsPos& dest, const mavsdk::Telemetry::Position& src) { ASSIGN_MEMBER(dest, src, latitude_deg); ASSIGN_MEMBER(dest, src, longitude_deg); ASSIGN_MEMBER(dest, src, absolute_altitude_m); ASSIGN_MEMBER(dest, src, relative_altitude_m); }
优势说明
- 编译期完成所有赋值逻辑,没有运行时额外开销,和手动赋值效率完全相同
- 扩展性强:如果后续需要处理其他结构体对,只需要新增
assign_members的特化版本,添加对应的成员映射即可 - 减少重复代码,避免手动赋值时可能出现的遗漏或笔误
内容的提问来源于stack exchange,提问作者InKronos
相关产品推荐
相关产品推荐

