You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将结构体/类的属性而非属性值作为模板/函数参数?

如何用模板参数传递类的成员属性实现通用取值函数

要实现你想要的通用属性获取函数,核心是利用类成员指针作为模板参数——这是唯一符合你限制条件(无宏/字符串、支持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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 18:50:04