C 获得超载成员功能指针的通用方法
C++ common way to get overloaded member function pointer
获取超载成员函数地址的常见方法是什么(实际成员和静态成员带有替代通话约定)?
下面的示例在替代呼叫约定的情况下失败:
#include <iostream>
using namespace std;
struct A {
int mem(int a) {
return a * 2;
};
int mem(int a, int b) {
return a + b;
}
static int stat(int a) {
return a * 2;
}
static int stat(int a, int b) {
return a + b;
}
};
int main() {
A a;
cout << "a.mem(1) -> " << a.mem(1) << endl;
cout << "a.mem(1, 2) -> " << a.mem(1, 2) << endl;
cout << "A::stat(1) -> " << A::stat(1) << endl;
cout << "A::stat(1, 2) -> " << A::stat(1, 2) << endl;
cout << "a.stat(1) -> " << a.stat(1) << endl;
cout << "a.stat(1, 2) -> " << a.stat(1, 2) << endl;
cout << "----------------------------------" << endl;
auto aMem1 = static_cast<int(A::*)(int)>(&A::mem);
cout << "a.*aMem1(1) -> " << (a.*aMem1)(1) << endl;
auto aMem2 = static_cast<int(A::*)(int, int)>(&A::mem);
cout << "a.*aMem2(1, 2) -> " << (a.*aMem2)(1, 2) << endl;
auto stat1 = static_cast<int(*)(int)>(&A::stat);
cout << "stat1(1) -> " << stat1(1) << endl;
auto stat2 = static_cast<int(*)(int, int)>(&A::stat);
cout << "stat2(1, 2) -> " << stat2(1, 2) << endl;
// these fail:
auto aStat1 = static_cast<int(A::*)(int)>(&A::stat);
cout << "a.*aStat1(1) -> " << (a.*aStat1)(1) << endl;
auto aStat2 = static_cast<int(A::*)(int, int)>(&A::stat);
cout << "a.*aStat2(1, 2) -> " << (a.*aStat2)(1, 2) << endl;
return 0;
}
请参见实时示例。
背景:
我不知道该实现是否使用成员功能或静态成员函数,因此,我需要一种处理两者的常见方法。如上所述,显而易见的方法不是成功的。
如果您需要能够以相同的方式对待表达式&A::x
,无论x
是A
的静态还是静态成员(并且可能已重载),则您需要要通过其他一些超载功能,这些功能可以接受R(C::*)(Ts...)
或R(C::*)(Ts...)const
或R(*)(Ts...)
并相应地分配。这样的东西:
template <typename... Ts>
struct UniformResolver {
template <typename C, typename R>
constexpr auto operator()(R (C::*func)(Ts...)) const { return resolveMember(func); }
template <typename C, typename R>
constexpr auto operator()(R (C::*func)(Ts...) const) const { return resolveMember(func); }
template <typename R>
constexpr auto operator()(R (*func)(Ts...)) const { return resolveStatic(func); }
private:
template <typename F>
constexpr auto resolveMember(F func) const {
return [func](auto&&... args) {
return std::invoke(func, std::forward<decltype(args)>(args)...);
};
}
template <typename F>
constexpr auto resolveStatic(F func) const {
return [func](auto&&, auto&&... args) {
return std::invoke(func, std::forward<decltype(args)>(args)...);
};
}
};
template <typename... Ts>
constexpr UniformResolver<Ts...> uresolve {};
这为您提供了一个可呼叫的对象模板uresolve
,该模板可以调整您的功能指针,返回可以以统一的方式调用的可调用对象,并将其委派给您的函数指针。这就是您的使用方式:
struct A {
int mem(int a) const { return a * 2; }
int mem(int a, int b) const { return a + b; }
static int stat(int a) { return a * 2; }
static int stat(int a, int b) { return a + b; }
};
int main() {
A a;
auto mem1 = uresolve<int>(&A::mem);
auto mem2 = uresolve<int, int>(&A::mem);
auto stat1 = uresolve<int>(&A::stat);
auto stat2 = uresolve<int, int>(&A::stat);
std::cout << mem1(a, 1) << 'n';
std::cout << mem2(a, 1, 2) << 'n';
std::cout << stat1(a, 1) << 'n';
std::cout << stat2(a, 1, 2) << 'n';
}
实时演示
可以使用具有相似声明的功能,可以使用单个变量std::function
。
具有单个参数的函数:
std::function< int(int) > func_1_param;
func_1_param = static_cast< int (*)(int) >(&A::stat);
cout << "int(int)->" << func_1_param(1) << endl;
using std::placeholders::_1;
func_1_param = std::bind(static_cast< int (A::*)(int) >(&A::mem), &a, _1);
cout << "int(int)->" << func_1_param(1) << endl;
函数2个参数;
std::function< int(int, int) > func_2_param;
func_2_param = static_cast< int (*)(int, int) >(&A::stat);
cout << "int(int, int)->" << func_2_param(1, 2) << endl;
using std::placeholders::_1;
using std::placeholders::_2;
func_2_param = std::bind(static_cast< int (A::*)(int, int) >(&A::mem), &a, _1, _2);
cout << "int(int, int)->" << func_2_param(1, 2) << endl;
可以使用lambda,而不是使用std::bind
。
据我所知,没有办法将静态成员函数施加到成员函数指针中以通用方式解决过载或任何其他直接方法。
从JAROD42拾取提示通过某些代理类,功能或在这种情况下为Lambda提供了以下解决方案(只要它是非捕获):
#include <iostream>
using namespace std;
struct A {
int mem(int a) {
return a * 2;
};
int mem(int a, int b) {
return a + b;
}
static int stat(int a) {
return a * 2;
}
static int stat(int a, int b) {
return a + b;
}
};
static A a;
int main() {
typedef int(*type1)(int);
typedef int(*type2)(int, int);
cout << "a.mem(1) -> " << a.mem(1) << endl;
cout << "a.mem(1, 2) -> " << a.mem(1, 2) << endl;
cout << "A::stat(1) -> " << A::stat(1) << endl;
cout << "A::stat(1, 2) -> " << A::stat(1, 2) << endl;
cout << "a.stat(1) -> " << a.stat(1) << endl;
cout << "a.stat(1, 2) -> " << a.stat(1, 2) << endl;
cout << "----------------------------------" << endl;
type1 aMem1 = [] (int a0) -> int { return a.mem(a0); };
cout << "aMem1(1) -> " << aMem1(1) << endl;
type2 aMem2 = [] (int a0, int a1) -> int { return a.mem(a0, a1); };
cout << "aMem2(1, 2) -> " << aMem2(1, 2) << endl;
type1 stat1 = [] (int a0) -> int { return A::stat(a0); };
cout << "stat1(1) -> " << stat1(1) << endl;
type2 stat2 = [] (int a0, int a1) -> int { return A::stat(a0, a1); };
cout << "stat2(1, 2) -> " << stat2(1, 2) << endl;
type1 aStat1 = [] (int a0) -> int { return a.stat(a0); };
cout << "aStat1(1) -> " << aStat1(1) << endl;
type2 aStat2 = [] (int a0, int a1) -> int { return a.stat(a0, a1); };
cout << "aStat2(1, 2) -> " << aStat2(1, 2) << endl;
return 0;
}
请参见实时示例。
这通过使用与用户强制执行的相同的呼叫约定来利用原始问题。这意味着,如果用户能够以这种方式调用成员函数(无论是否静态),那么我们也是因为我们正在使用相同的呼叫约定。人们可以通过使用代理类继续使用成员函数指针。对我来说,lambda方法效果更好。
相关文章:
- 将一个类的方法指针存储到另一个类中
- 如何调用返回类方法指针的类方法
- 通过reinterpret_casting方法指针从指针调用派生类的方法。这是 UB 吗?
- 泛型方法指针.reinterpret_cast指向不同类的方法指针,这是 UB 吗?
- C++;类方法指针;λ;将 lambda 作为成员函数指针传递;
- 使用模板、方法指针和字符串键入推导
- 将方法指针作为整数参数发送到C#的C 方法
- 从C 中的VTable获取方法指针
- 模板化方法指针 - 无法匹配函数参数的指针
- 获取特定的模板重载方法指针
- 如何将方法指针声明为Typedef方法参数
- 如何将方法指针类型转换为函数指针类型
- 如何在使用 pthreads 时将方法指针作为函数参数传递C++
- 方法指针映射,编译器说他们不接受任何参数
- C# 方法指针,如 C++ 中的指针
- c++创建新的LinkedList类:Clear()方法指针被释放未分配
- 尝试获取类方法指针时出现E_NOINTERFACE
- 传递和强制转换方法指针
- 常量方法指针的类型是什么
- 将对象的方法指针传递给接受 [静态方法指针/全局函数] 指针的函数