C++是否可创建通用函数,设置传入struct结构体的对应成员?
实现方案
你要实现的功能有两种主流的实现方式,都基于模板,且完全类型安全,不需要用到不安全的void*传参。
方案1:传入成员指针(灵活适配任意成员,推荐)
这种方式支持你修改任意结构体的任意可写成员,编译期完成所有类型检查,零运行时开销。
C++11及以上兼容版本
#include <iostream> struct A { int x; int y; }; struct B { double z; }; // 模板参数依次为:结构体类型、成员变量类型、指向目标成员的指针 template<typename ObjT, typename MemT, MemT ObjT::*Member> void change(ObjT& obj, const MemT& value) { obj.*Member = value; } int main(void) { A a; B b; int valueA = 5; double valueB = 10.3; change<A, int, &A::x>(a, valueA); change<B, double, &B::z>(b, valueB); // 验证结果 std::cout << a.x << std::endl; // 输出5 std::cout << b.z << std::endl; // 输出10.3 return 0; }
C++17简化版本
C++17支持auto作为非类型模板参数,可以自动推导成员指针类型,调用时写法更简洁:
// C++17版change函数 template<auto Member, typename ObjT, typename MemT> void change(ObjT& obj, const MemT& value) { obj.*Member = value; } // 调用时只需要指定成员指针即可 change<&A::x>(a, valueA); change<&B::z>(b, valueB); // 也可以灵活修改A的其他成员 change<&A::y>(a, 10);
方案2:模板特化(固定每个结构体的目标修改成员)
如果每个结构体只需要修改固定的某一个默认成员,不需要动态指定,可以用模板特化实现,调用方式和你示例的写法完全一致:
#include <iostream> struct A { int x; int y; }; struct B { double z; }; // 通用模板声明 template<typename T> void change(T& obj, const decltype(auto) value); // 特化A的实现,默认修改x成员 template<> void change<A>(A& obj, const int& value) { obj.x = value; } // 特化B的实现,默认修改z成员 template<> void change<B>(B& obj, const double& value) { obj.z = value; } int main(void) { A a; B b; int valueA = 5; double valueB = 10.3; change(a, valueA); // 自动匹配A的特化版本 change(b, valueB); // 自动匹配B的特化版本 std::cout << a.x << std::endl; // 输出5 std::cout << b.z << std::endl; // 输出10.3 return 0; }
原有代码的问题说明
- 第一个参数按值传递:函数内修改的是栈上的临时副本,不会影响外部的原变量,必须改为传引用或者指针
void*传参丢失类型信息,没有编译期类型检查,容易触发未定义行为,不建议使用
内容的提问来源于stack exchange,提问作者Jazzy
相关产品推荐
相关产品推荐

