在其自己的模板化成员方法中获取 class 的类型
Get type of class within its own templated member method
这有点令人困惑,但我会尽力解释。我有一组宏可以帮助我编写特殊的成员方法,这些方法在成员方法调用周围添加一个包装器。
例如:
class Test {
public:
DECLARE_METHOD(int, methodName, (int, a) (AMoveOnlyType, b));
};
扩展为如下内容:
class Test {
public:
int methodName(int a, AMoveOnlyType b);
int methodName_WRAPPER(int a, AMoveOnlyType b);
};
我有一个相应的源文件宏:
//in .cpp file
DECLARE_METHOD(int, Test::methodName, (int, a) (AMoveOnlyType, b)) {
//body of the method here
}
扩展为如下内容:
int Test::methodName(int a, AMoveOnlyType b) {
//Assume I have a templated function which allows me to queue and call a function at some later point in time
return execute_later(this, &Test::methodName_WRAPPER, a, b);
}
int Test::methodName_WRAPPER(int a, AMoveOnlyType b) {
//body of the method here
}
但是,我意识到我需要能够完美地将传递给 methodName
的参数转发到我在包装代码中所做的任何事情。实现此目的的唯一方法是使 methodName
成为模板函数,这反过来意味着它需要在 header 文件中定义。所以我的 DECLARE_METHOD 宏会扩展成这样:
class Test {
public:
template <typename ... ARGS>
inline int methodName(ARGS&&... args) {
return execute_later(this, &methodName_WRAPPER, std::forward<ARGS>(args)...);
}
int methodName_WRAPPER(int a, AMoveOnlyType b);
};
这样我就可以像这样使用它了:
Test instance;
AMoveOnlyType x;
//I can't write a macro which magically knows if the wrapper needs to move/forward the arguments so this is why I needed to use a template
instance.methodName(1, std::move(x));
问题是,我收到以下错误“ISO C++ 禁止使用绑定成员函数的地址来形成指向成员函数的指针”
我知道我需要像在 DEFINE_METHOD
宏中那样提供函数的全名。但是,由于这是在 header 文件中,我真的更愿意像以前一样使用我的 DECLARE_METHOD
宏,而不必冗余地提供 class 的名称(就像你一样在 class).
中声明普通方法时会
我的问题是,有没有办法以某种方式获取指向 header 中的 class' 成员方法的指针,而无需提供其全名?
如果我需要澄清任何事情,请告诉我。
作为旁注,我真的很想在不影响以下语句的范围,但我看不到执行此操作的方法。
编辑
根据评论中的要求,这里是宏:
/**
* @brief This macro will remove parenthesis from around its argument only
* if they are present.
*
* See
*/
#define DEPAREN(X) ESC(ISH X)
#define ISH(...) ISH __VA_ARGS__
#define ESC(...) ESC_(__VA_ARGS__)
#define ESC_(...) VAN ## __VA_ARGS__
#define VANISH
#define END(...) END_(__VA_ARGS__)
#define END_(...) __VA_ARGS__##_END
#define END_C(...) END_C_(__VA_ARGS__)
#define END_C_(...) __VA_ARGS__##_END_C
//------------------------------------------------------------------------------
#define PARAMS_LOOP(...) END(PARAMS_LOOP_0 __VA_ARGS__)
#define PARAMS_LOOP_C(...) END_C(PARAMS_LOOP_0_C __VA_ARGS__)
#define PARAMS_LOOP_C_POST(...) END_C(PARAMS_LOOP_0 __VA_ARGS__)
#define PARAMS_LOOP_C_PRE(...) END(PARAMS_LOOP_0_C __VA_ARGS__)
#define PARAMS_LOOP_MACRO(_1, _2, _3, NAME, ...) NAME
#define PARAMS_LOOP_BODY(...) PARAMS_LOOP_MACRO(__VA_ARGS__, PARAMS_LOOP_BODY3, PARAMS_LOOP_BODY2)(__VA_ARGS__)
#define PARAMS_LOOP_BODY2(type_, name_, ...) DEPAREN(type_) name_
#define PARAMS_LOOP_BODY3(type_, name_, default_, ...) DEPAREN(type_) name_ = default_
#define PARAMS_LOOP_0(...) PARAMS_LOOP_BODY(__VA_ARGS__) PARAMS_LOOP_A
#define PARAMS_LOOP_0_C(...) , PARAMS_LOOP_BODY(__VA_ARGS__) PARAMS_LOOP_A
#define PARAMS_LOOP_A(...) , PARAMS_LOOP_BODY(__VA_ARGS__) PARAMS_LOOP_B
#define PARAMS_LOOP_B(...) , PARAMS_LOOP_BODY(__VA_ARGS__) PARAMS_LOOP_A
#define PARAMS_LOOP_0_END
#define PARAMS_LOOP_0_END_C
#define PARAMS_LOOP_0_C_END
#define PARAMS_LOOP_0_C_END_C ,
#define PARAMS_LOOP_A_END
#define PARAMS_LOOP_A_END_C ,
#define PARAMS_LOOP_B_END
#define PARAMS_LOOP_B_END_C ,
//------------------------------------------------------------------------------
/**
* Examples 1:
* NTH_LOOP(1, (int, a) (char, b) (uint8_t, c))
* END(NTH_LOOP_0_1 (int, a) (char, b) (uint8_t, c))
* NTH_LOOP_BODY_0(int, a) NTH_LOOP_A_0 (char, b) (uint8_t, c)_END
* DEPAREN(a), NTH_LOOP_BODY_0(char, b) NTH_LOOP_B_0(uint8_t, c)_END
* a, DEPAREN(b), NTH_LOOP_BODY_0(uint8_t, c) NTH_LOOP_A_1_END
* a, b, DEPAREN(c)
* a, b, c
*
* Example 2:
* NTH_LOOP(0)
* END(NTH_LOOP_0_0_END)
*
*/
#define NTH_LOOP(n_, ...) END(NTH_LOOP_0_ ## n_ __VA_ARGS__)
/**
* @brief Build a list containing the Nth arguments prefixed and postfixed by a
* comma.
*
* Example 1:
* NTH_LOOP_C(0)
* END(NTH_LOOP_0_0_C_END)
* ,
*
*/
#define NTH_LOOP_C(n_, ...) END_C(NTH_LOOP_0_ ## n_ ## _C __VA_ARGS__)
/**
* @brief Build a list containing the Nth arguments postfixed by a comma.
*
* **Example 1:**\n
* NTH_LOOP_C_POST(0)\n
* END(NTH_LOOP_0_0_C_END)\n
* ,\n
* \n
* **Example 2:**\n
* NTH_LOOP_C_POST(0, (int, a) (char, b))\n
* int, char,\n
*/
#define NTH_LOOP_C_POST(n_, ...) END_C(NTH_LOOP_0_ ## n_ __VA_ARGS__)
/**
* @brief Build a list containing the Nth arguments prefixed by a comma.
*
* **Example 1:**\n
* NTH_LOOP_C_PRE(0)\n
* END(NTH_LOOP_0_0_C_END)\n
* \n
* \n
* **Example 2:**\n
* NTH_LOOP_C_PRE(0, (int, a) (char, b))\n
* , int, char\n
*/
#define NTH_LOOP_C_PRE(n_, ...) END(NTH_LOOP_0_ ## n_ ## _C __VA_ARGS__)
#define NTH_LOOP_0_0(...) NTH_LOOP_BODY_0(__VA_ARGS__) NTH_LOOP_A_0
#define NTH_LOOP_0_0_C(...) , NTH_LOOP_BODY_0(__VA_ARGS__) NTH_LOOP_A_0
#define NTH_LOOP_A_0(...) , NTH_LOOP_BODY_0(__VA_ARGS__) NTH_LOOP_B_0
#define NTH_LOOP_B_0(...) , NTH_LOOP_BODY_0(__VA_ARGS__) NTH_LOOP_A_0
#define NTH_LOOP_0_0_END
#define NTH_LOOP_0_0_END_C
#define NTH_LOOP_0_0_C_END
#define NTH_LOOP_0_0_C_END_C ,
#define NTH_LOOP_A_0_END
#define NTH_LOOP_A_0_END_C ,
#define NTH_LOOP_B_0_END
#define NTH_LOOP_B_0_END_C ,
#define NTH_LOOP_BODY_0(arg0_, ...) DEPAREN(arg0_)
#define NTH_LOOP_0_1(...) NTH_LOOP_BODY_1(__VA_ARGS__) NTH_LOOP_A_1
#define NTH_LOOP_0_1_C(...) , NTH_LOOP_BODY_1(__VA_ARGS__) NTH_LOOP_A_1
#define NTH_LOOP_A_1(...) , NTH_LOOP_BODY_1(__VA_ARGS__) NTH_LOOP_B_1
#define NTH_LOOP_B_1(...) , NTH_LOOP_BODY_1(__VA_ARGS__) NTH_LOOP_A_1
#define NTH_LOOP_0_1_END
#define NTH_LOOP_0_1_END_C
#define NTH_LOOP_0_1_C_END
#define NTH_LOOP_0_1_C_END_C ,
#define NTH_LOOP_A_1_END
#define NTH_LOOP_A_1_END_C ,
#define NTH_LOOP_B_1_END
#define NTH_LOOP_B_1_END_C ,
#define NTH_LOOP_BODY_1(arg0_, arg1_, ...) DEPAREN(arg1_)
#define NTH_LOOP_0_2(...) NTH_LOOP_BODY_2(__VA_ARGS__) NTH_LOOP_A_2
#define NTH_LOOP_0_2_C(...) , NTH_LOOP_BODY_2(__VA_ARGS__) NTH_LOOP_A_2
#define NTH_LOOP_A_2(...) , NTH_LOOP_BODY_2(__VA_ARGS__) NTH_LOOP_B_2
#define NTH_LOOP_B_2(...) , NTH_LOOP_BODY_2(__VA_ARGS__) NTH_LOOP_A_2
#define NTH_LOOP_0_2_END
#define NTH_LOOP_0_2_END_C
#define NTH_LOOP_0_2_C_END
#define NTH_LOOP_0_2_C_END_C ,
#define NTH_LOOP_A_2_END
#define NTH_LOOP_A_2_END_C ,
#define NTH_LOOP_B_2_END
#define NTH_LOOP_B_2_END_C ,
#define NTH_LOOP_BODY_2(arg0_, arg1_, arg2_, ...) DEPAREN(arg2_)
#define NTH_LOOP_0_3(...) NTH_LOOP_BODY_3(__VA_ARGS__) NTH_LOOP_A_3
#define NTH_LOOP_0_3_C(...) , NTH_LOOP_BODY_3(__VA_ARGS__) NTH_LOOP_A_3
#define NTH_LOOP_A_3(...) , NTH_LOOP_BODY_3(__VA_ARGS__) NTH_LOOP_B_3
#define NTH_LOOP_B_3(...) , NTH_LOOP_BODY_3(__VA_ARGS__) NTH_LOOP_A_3
#define NTH_LOOP_0_3_END
#define NTH_LOOP_0_3_END_C
#define NTH_LOOP_0_3_C_END
#define NTH_LOOP_0_3_C_END_C ,
#define NTH_LOOP_A_3_END
#define NTH_LOOP_A_3_END_C ,
#define NTH_LOOP_B_3_END
#define NTH_LOOP_B_3_END_C ,
#define NTH_LOOP_BODY_3(arg0_, arg1_, arg2_, arg3_, ...) DEPAREN(arg3_)
#define DECLARE_METHOD(ret_, func_, ...) \
template <typename ... ARGS>\
inline ret_ func_(ARGS&&... args) {\
return execute_later(this, &func_, std::forward<ARGS>(args)...);\
}\
ret_ func_##_WRAPPER(PARAMS_LOOP(__VA_ARGS__))
#define DEFINE_METHOD(ret_, func_, ...) \
ret_ func_##_WRAPPER(PARAMS_LOOP(__VA_ARGS__))
您不需要 class 的确切名称,任何解析为 class 类型的内容都将用于指向成员语法的指针。由于您在非静态成员函数中,只需将宏扩展为
template <typename ... ARGS>
int methodName(ARGS&&... args) {
return execute_later(this, &std::remove_cv_t<std::remove_reference_t<decltype(*this)>>::methodName_WRAPPER, std::forward<ARGS>(args)...);
}
有点啰嗦,不过看在宏的后面,不会太突出。
就将所有 _WRAPPER
方法设为私有而言,这有点棘手。您当然可以充分利用 Java 并生成
public: int foo(...) { ... }
private: int foo_WRAPPER(...) { ... }
但它会影响宏之后的任何声明,无论您如何排列其中的两个声明。这不太理想。
另一种解决方案是使用密码习惯用法。以某种方式将标记类型添加到 class 中。 CRTP是一种方式:
template<class D>
class MethodDeclarer {
struct tag_t{ explicit tag_t() = default; };
friend D;
};
然后结合宏使用
class Test : MethodDeclarer<Test> {
};
它给了我们什么? Test
独有的私有类型,只有它可以访问。然后您可以将宏扩展为
template <typename ... ARGS>
int methodName(ARGS&&... args) {
return execute_later(this, &std::remove_cv_t<std::remove_reference_t<decltype(*this)>>::methodName_WRAPPER, tag_t{}, std::forward<ARGS>(args)...);
}
int methodName_WRAPPER(tag_t, int a, AMoveOnlyType b);
当然,_WRAPPER
是 public,但它需要 tag_t
才能调用,而且只有 Test
才能创建这些。这种技术实质上将访问说明符转换为要传递的值。
这有点令人困惑,但我会尽力解释。我有一组宏可以帮助我编写特殊的成员方法,这些方法在成员方法调用周围添加一个包装器。
例如:
class Test {
public:
DECLARE_METHOD(int, methodName, (int, a) (AMoveOnlyType, b));
};
扩展为如下内容:
class Test {
public:
int methodName(int a, AMoveOnlyType b);
int methodName_WRAPPER(int a, AMoveOnlyType b);
};
我有一个相应的源文件宏:
//in .cpp file
DECLARE_METHOD(int, Test::methodName, (int, a) (AMoveOnlyType, b)) {
//body of the method here
}
扩展为如下内容:
int Test::methodName(int a, AMoveOnlyType b) {
//Assume I have a templated function which allows me to queue and call a function at some later point in time
return execute_later(this, &Test::methodName_WRAPPER, a, b);
}
int Test::methodName_WRAPPER(int a, AMoveOnlyType b) {
//body of the method here
}
但是,我意识到我需要能够完美地将传递给 methodName
的参数转发到我在包装代码中所做的任何事情。实现此目的的唯一方法是使 methodName
成为模板函数,这反过来意味着它需要在 header 文件中定义。所以我的 DECLARE_METHOD 宏会扩展成这样:
class Test {
public:
template <typename ... ARGS>
inline int methodName(ARGS&&... args) {
return execute_later(this, &methodName_WRAPPER, std::forward<ARGS>(args)...);
}
int methodName_WRAPPER(int a, AMoveOnlyType b);
};
这样我就可以像这样使用它了:
Test instance;
AMoveOnlyType x;
//I can't write a macro which magically knows if the wrapper needs to move/forward the arguments so this is why I needed to use a template
instance.methodName(1, std::move(x));
问题是,我收到以下错误“ISO C++ 禁止使用绑定成员函数的地址来形成指向成员函数的指针”
我知道我需要像在 DEFINE_METHOD
宏中那样提供函数的全名。但是,由于这是在 header 文件中,我真的更愿意像以前一样使用我的 DECLARE_METHOD
宏,而不必冗余地提供 class 的名称(就像你一样在 class).
我的问题是,有没有办法以某种方式获取指向 header 中的 class' 成员方法的指针,而无需提供其全名?
如果我需要澄清任何事情,请告诉我。
作为旁注,我真的很想在不影响以下语句的范围,但我看不到执行此操作的方法。
编辑
根据评论中的要求,这里是宏:
/**
* @brief This macro will remove parenthesis from around its argument only
* if they are present.
*
* See
*/
#define DEPAREN(X) ESC(ISH X)
#define ISH(...) ISH __VA_ARGS__
#define ESC(...) ESC_(__VA_ARGS__)
#define ESC_(...) VAN ## __VA_ARGS__
#define VANISH
#define END(...) END_(__VA_ARGS__)
#define END_(...) __VA_ARGS__##_END
#define END_C(...) END_C_(__VA_ARGS__)
#define END_C_(...) __VA_ARGS__##_END_C
//------------------------------------------------------------------------------
#define PARAMS_LOOP(...) END(PARAMS_LOOP_0 __VA_ARGS__)
#define PARAMS_LOOP_C(...) END_C(PARAMS_LOOP_0_C __VA_ARGS__)
#define PARAMS_LOOP_C_POST(...) END_C(PARAMS_LOOP_0 __VA_ARGS__)
#define PARAMS_LOOP_C_PRE(...) END(PARAMS_LOOP_0_C __VA_ARGS__)
#define PARAMS_LOOP_MACRO(_1, _2, _3, NAME, ...) NAME
#define PARAMS_LOOP_BODY(...) PARAMS_LOOP_MACRO(__VA_ARGS__, PARAMS_LOOP_BODY3, PARAMS_LOOP_BODY2)(__VA_ARGS__)
#define PARAMS_LOOP_BODY2(type_, name_, ...) DEPAREN(type_) name_
#define PARAMS_LOOP_BODY3(type_, name_, default_, ...) DEPAREN(type_) name_ = default_
#define PARAMS_LOOP_0(...) PARAMS_LOOP_BODY(__VA_ARGS__) PARAMS_LOOP_A
#define PARAMS_LOOP_0_C(...) , PARAMS_LOOP_BODY(__VA_ARGS__) PARAMS_LOOP_A
#define PARAMS_LOOP_A(...) , PARAMS_LOOP_BODY(__VA_ARGS__) PARAMS_LOOP_B
#define PARAMS_LOOP_B(...) , PARAMS_LOOP_BODY(__VA_ARGS__) PARAMS_LOOP_A
#define PARAMS_LOOP_0_END
#define PARAMS_LOOP_0_END_C
#define PARAMS_LOOP_0_C_END
#define PARAMS_LOOP_0_C_END_C ,
#define PARAMS_LOOP_A_END
#define PARAMS_LOOP_A_END_C ,
#define PARAMS_LOOP_B_END
#define PARAMS_LOOP_B_END_C ,
//------------------------------------------------------------------------------
/**
* Examples 1:
* NTH_LOOP(1, (int, a) (char, b) (uint8_t, c))
* END(NTH_LOOP_0_1 (int, a) (char, b) (uint8_t, c))
* NTH_LOOP_BODY_0(int, a) NTH_LOOP_A_0 (char, b) (uint8_t, c)_END
* DEPAREN(a), NTH_LOOP_BODY_0(char, b) NTH_LOOP_B_0(uint8_t, c)_END
* a, DEPAREN(b), NTH_LOOP_BODY_0(uint8_t, c) NTH_LOOP_A_1_END
* a, b, DEPAREN(c)
* a, b, c
*
* Example 2:
* NTH_LOOP(0)
* END(NTH_LOOP_0_0_END)
*
*/
#define NTH_LOOP(n_, ...) END(NTH_LOOP_0_ ## n_ __VA_ARGS__)
/**
* @brief Build a list containing the Nth arguments prefixed and postfixed by a
* comma.
*
* Example 1:
* NTH_LOOP_C(0)
* END(NTH_LOOP_0_0_C_END)
* ,
*
*/
#define NTH_LOOP_C(n_, ...) END_C(NTH_LOOP_0_ ## n_ ## _C __VA_ARGS__)
/**
* @brief Build a list containing the Nth arguments postfixed by a comma.
*
* **Example 1:**\n
* NTH_LOOP_C_POST(0)\n
* END(NTH_LOOP_0_0_C_END)\n
* ,\n
* \n
* **Example 2:**\n
* NTH_LOOP_C_POST(0, (int, a) (char, b))\n
* int, char,\n
*/
#define NTH_LOOP_C_POST(n_, ...) END_C(NTH_LOOP_0_ ## n_ __VA_ARGS__)
/**
* @brief Build a list containing the Nth arguments prefixed by a comma.
*
* **Example 1:**\n
* NTH_LOOP_C_PRE(0)\n
* END(NTH_LOOP_0_0_C_END)\n
* \n
* \n
* **Example 2:**\n
* NTH_LOOP_C_PRE(0, (int, a) (char, b))\n
* , int, char\n
*/
#define NTH_LOOP_C_PRE(n_, ...) END(NTH_LOOP_0_ ## n_ ## _C __VA_ARGS__)
#define NTH_LOOP_0_0(...) NTH_LOOP_BODY_0(__VA_ARGS__) NTH_LOOP_A_0
#define NTH_LOOP_0_0_C(...) , NTH_LOOP_BODY_0(__VA_ARGS__) NTH_LOOP_A_0
#define NTH_LOOP_A_0(...) , NTH_LOOP_BODY_0(__VA_ARGS__) NTH_LOOP_B_0
#define NTH_LOOP_B_0(...) , NTH_LOOP_BODY_0(__VA_ARGS__) NTH_LOOP_A_0
#define NTH_LOOP_0_0_END
#define NTH_LOOP_0_0_END_C
#define NTH_LOOP_0_0_C_END
#define NTH_LOOP_0_0_C_END_C ,
#define NTH_LOOP_A_0_END
#define NTH_LOOP_A_0_END_C ,
#define NTH_LOOP_B_0_END
#define NTH_LOOP_B_0_END_C ,
#define NTH_LOOP_BODY_0(arg0_, ...) DEPAREN(arg0_)
#define NTH_LOOP_0_1(...) NTH_LOOP_BODY_1(__VA_ARGS__) NTH_LOOP_A_1
#define NTH_LOOP_0_1_C(...) , NTH_LOOP_BODY_1(__VA_ARGS__) NTH_LOOP_A_1
#define NTH_LOOP_A_1(...) , NTH_LOOP_BODY_1(__VA_ARGS__) NTH_LOOP_B_1
#define NTH_LOOP_B_1(...) , NTH_LOOP_BODY_1(__VA_ARGS__) NTH_LOOP_A_1
#define NTH_LOOP_0_1_END
#define NTH_LOOP_0_1_END_C
#define NTH_LOOP_0_1_C_END
#define NTH_LOOP_0_1_C_END_C ,
#define NTH_LOOP_A_1_END
#define NTH_LOOP_A_1_END_C ,
#define NTH_LOOP_B_1_END
#define NTH_LOOP_B_1_END_C ,
#define NTH_LOOP_BODY_1(arg0_, arg1_, ...) DEPAREN(arg1_)
#define NTH_LOOP_0_2(...) NTH_LOOP_BODY_2(__VA_ARGS__) NTH_LOOP_A_2
#define NTH_LOOP_0_2_C(...) , NTH_LOOP_BODY_2(__VA_ARGS__) NTH_LOOP_A_2
#define NTH_LOOP_A_2(...) , NTH_LOOP_BODY_2(__VA_ARGS__) NTH_LOOP_B_2
#define NTH_LOOP_B_2(...) , NTH_LOOP_BODY_2(__VA_ARGS__) NTH_LOOP_A_2
#define NTH_LOOP_0_2_END
#define NTH_LOOP_0_2_END_C
#define NTH_LOOP_0_2_C_END
#define NTH_LOOP_0_2_C_END_C ,
#define NTH_LOOP_A_2_END
#define NTH_LOOP_A_2_END_C ,
#define NTH_LOOP_B_2_END
#define NTH_LOOP_B_2_END_C ,
#define NTH_LOOP_BODY_2(arg0_, arg1_, arg2_, ...) DEPAREN(arg2_)
#define NTH_LOOP_0_3(...) NTH_LOOP_BODY_3(__VA_ARGS__) NTH_LOOP_A_3
#define NTH_LOOP_0_3_C(...) , NTH_LOOP_BODY_3(__VA_ARGS__) NTH_LOOP_A_3
#define NTH_LOOP_A_3(...) , NTH_LOOP_BODY_3(__VA_ARGS__) NTH_LOOP_B_3
#define NTH_LOOP_B_3(...) , NTH_LOOP_BODY_3(__VA_ARGS__) NTH_LOOP_A_3
#define NTH_LOOP_0_3_END
#define NTH_LOOP_0_3_END_C
#define NTH_LOOP_0_3_C_END
#define NTH_LOOP_0_3_C_END_C ,
#define NTH_LOOP_A_3_END
#define NTH_LOOP_A_3_END_C ,
#define NTH_LOOP_B_3_END
#define NTH_LOOP_B_3_END_C ,
#define NTH_LOOP_BODY_3(arg0_, arg1_, arg2_, arg3_, ...) DEPAREN(arg3_)
#define DECLARE_METHOD(ret_, func_, ...) \
template <typename ... ARGS>\
inline ret_ func_(ARGS&&... args) {\
return execute_later(this, &func_, std::forward<ARGS>(args)...);\
}\
ret_ func_##_WRAPPER(PARAMS_LOOP(__VA_ARGS__))
#define DEFINE_METHOD(ret_, func_, ...) \
ret_ func_##_WRAPPER(PARAMS_LOOP(__VA_ARGS__))
您不需要 class 的确切名称,任何解析为 class 类型的内容都将用于指向成员语法的指针。由于您在非静态成员函数中,只需将宏扩展为
template <typename ... ARGS>
int methodName(ARGS&&... args) {
return execute_later(this, &std::remove_cv_t<std::remove_reference_t<decltype(*this)>>::methodName_WRAPPER, std::forward<ARGS>(args)...);
}
有点啰嗦,不过看在宏的后面,不会太突出。
就将所有 _WRAPPER
方法设为私有而言,这有点棘手。您当然可以充分利用 Java 并生成
public: int foo(...) { ... }
private: int foo_WRAPPER(...) { ... }
但它会影响宏之后的任何声明,无论您如何排列其中的两个声明。这不太理想。
另一种解决方案是使用密码习惯用法。以某种方式将标记类型添加到 class 中。 CRTP是一种方式:
template<class D>
class MethodDeclarer {
struct tag_t{ explicit tag_t() = default; };
friend D;
};
然后结合宏使用
class Test : MethodDeclarer<Test> {
};
它给了我们什么? Test
独有的私有类型,只有它可以访问。然后您可以将宏扩展为
template <typename ... ARGS>
int methodName(ARGS&&... args) {
return execute_later(this, &std::remove_cv_t<std::remove_reference_t<decltype(*this)>>::methodName_WRAPPER, tag_t{}, std::forward<ARGS>(args)...);
}
int methodName_WRAPPER(tag_t, int a, AMoveOnlyType b);
当然,_WRAPPER
是 public,但它需要 tag_t
才能调用,而且只有 Test
才能创建这些。这种技术实质上将访问说明符转换为要传递的值。