在类自身模板成员方法中获取类类型以取得成员函数指针的问题
解决方案
针对你遇到的两个核心问题,可以通过以下方式修改DECLARE_METHOD宏实现需求,且完全兼容原有使用方式:
1. 解决类内获取成员函数指针的编译错误
你遇到的编译报错是因为直接写&methodName_WRAPPER时,编译器会将其识别为绑定了当前this对象的成员函数引用,不符合成员函数指针的语法要求。我们可以通过decltype(*this)自动推导当前类的类型,无需手动传入类名:
- 在模板函数内部使用
std::remove_cvref_t<decltype(*this)>获取当前类的纯净类型(自动去除const、volatile、引用修饰符) - 基于推导的类类型拼接WRAPPER方法的完整成员函数指针
2. 实现WRAPPER方法私有且不影响后续作用域
由于你的DECLARE_METHOD生成的对外调用模板方法本身属于类的公共接口,默认应该放在类的public块中,我们可以在宏内手动切换访问权限:
- 生成公共模板方法后,切换到
private权限声明WRAPPER方法 - 声明完成后切回
public权限,保证后续类成员的默认访问权限和宏调用位置的预期一致
修改后的宏代码
你只需替换原有DECLARE_METHOD宏的定义即可:
#include <type_traits> #define DECLARE_METHOD(ret_, func_, ...) \ template <typename ... ARGS>\ inline ret_ func_(ARGS&&... args) {\ /* 自动推导当前类的类型,无需手动指定 */ \ using ClassType = std::remove_cvref_t<decltype(*this)>; \ return execute_later(this, &ClassType::func_##_WRAPPER, std::forward<ARGS>(args)...);\ }\ /* 切换到私有作用域声明WRAPPER */ \ private:\ ret_ func_##_WRAPPER(PARAMS_LOOP(__VA_ARGS__));\ /* 切回public作用域,不影响后续代码 */ \ public:
兼容性说明
如果使用的C版本低于C20,没有std::remove_cvref_t,可以替换为std::decay_t<decltype(*this)>,效果完全一致。
效果验证
修改后宏的展开效果完全符合预期:
// 你写的代码 class Test { public: DECLARE_METHOD(int, methodName, (int, a) (AMoveOnlyType, b)); // 后续的其他public成员不受影响 int other_public_func(); }; // 宏展开后等效代码 class Test { public: template <typename ... ARGS> inline int methodName(ARGS&&... args) { using ClassType = Test; return execute_later(this, &Test::methodName_WRAPPER, std::forward<ARGS>(args)...); } private: int methodName_WRAPPER(int a, AMoveOnlyType b); public: int other_public_func(); };
- WRAPPER方法为私有,外部无法直接调用
- 无需手动指定类名,完全兼容原有宏的使用方式
- 编译错误彻底解决
内容的提问来源于stack exchange,提问作者Patrick Wright
相关产品推荐
相关产品推荐

