如何将结构体/类的属性而非属性值作为模板/函数参数?
如何用模板参数传递类的成员属性实现通用取值函数
要实现你想要的通用属性获取函数,核心是利用类成员指针作为模板参数——这是唯一符合你限制条件(无宏/字符串、支持IDE提示、编译期处理)的解决方案,因为直接传递T::obj对于非静态成员来说是非法的(非静态成员不是编译期常量),而成员指针可以在编译期确定并指代类的某个属性。
不同C++版本的实现方案
C++17及以上(推荐)
C++17允许非类型模板参数使用auto,可以大幅简化模板定义,无需显式指定成员的类型:
#include <utility> // 用于std::forward template <typename T, auto MemPtr> decltype(auto) foo(T&& t) { // 使用std::forward保持值类别,避免不必要的拷贝 return std::forward<T>(t).*MemPtr; }
调用示例
对于普通结构体:
struct A { int b; double c; }; A a{42, 3.14}; // 获取a.b auto val_b = foo<A, &A::b>(a); // 获取a.c auto val_c = foo<A, &A::c>(a);
对于类模板:
template <typename U> struct B { U d; }; B<std::string> b{"hello"}; // 获取b.d auto val_d = foo<B<std::string>, &B<std::string>::d>(b);
C11/C14版本
如果需要兼容更早的C++标准,需要显式指定成员的类型:
template <typename T, typename MemType, MemType T::*MemPtr> MemType foo(T t) { return t.*MemPtr; }
调用示例
// 获取a.b auto val_b = foo<A, int, &A::b>(a); // 获取a.c auto val_c = foo<A, double, &A::c>(a);
方案优势
- IDE友好:输入
&A::时,IDE会自动列出类的所有成员,支持自动补全和类型提示 - 编译期安全:所有检查在编译阶段完成,不会有运行时开销
- 无宏/字符串操作:完全符合你的限制条件,避免了宏的可读性问题和字符串的运行时解析
- 支持类模板:对类模板的实例化类型同样有效,只需传递对应实例化类型的成员指针
关键说明
你最初设想的foo<A, A::b>(a)写法是不可行的——对于非静态成员,A::b不是一个合法的编译期常量,无法作为模板参数。而成员指针&A::b是编译期可确定的实体,是C++标准中唯一能合法指代类非静态成员的模板参数类型。
内容的提问来源于stack exchange,提问作者LibrarristShalinward
相关产品推荐
相关产品推荐

