如何获取成员函数指针的类
How can I get the class of a member function pointer?
考虑代码:
class Character
{
void kill();
void send_to_wall();
}
template <typename T>
void GeorgeFunc(T fp)
{
??? obj;
(obj.*fp)();
}
int main()
{
GeorgeFunc(&Character::kill);
}
所以我的问题是:我怎样才能得到???
?似乎编译器在模板实例化期间肯定知道这种类型是什么(Character
),但我不确定如何获得它。我目前的解决方法是更改为:void GeorgeFunc(void (T::*fp)())
,但简单地从成员函数指针获取类型会更干净。 decltype(fp)
会返回void(Character::*)()
,decltype(fp())
会返回void
。有什么方法可以得到Character
?
是的,只需使用特征来确定这一点。
template <typename> struct member_function_traits;
template <typename Return, typename Object, typename... Args>
struct member_function_traits<Return (Object::*)(Args...)>
{
typedef Return return_type;
typedef Object instance_type;
typedef Object & instance_reference;
// Can mess with Args... if you need to, for example:
static constexpr size_t argument_count = sizeof...(Args);
};
// If you intend to support const member functions you need another specialization.
template <typename Return, typename Object, typename... Args>
struct member_function_traits<Return (Object::*)(Args...) const>
{
typedef Return return_type;
typedef Object instance_type;
typedef Object const & instance_reference;
// Can mess with Args... if you need to, for example:
static constexpr size_t argument_count = sizeof...(Args);
};
现在您的声明是:
typename member_function_traits<T>::instance_type obj;
但是,我认为,由于您需要一个成员函数指针(由于第 1 行,其他类型的将无法实例化(obj.*fp)()
),因此您的函数应该直接采用成员函数指针而不是完全泛型的类型。
所以这个定义不仅有效,而且我认为它是首选的——当有人使用指向成员函数的指针以外的其他东西时,错误消息会更加清晰,因为参数类型将不兼容:
template <typename Return, typename Object>
void GeorgeFunc(Return (Object::*fp)())
{
Object obj;
(obj.*fp)();
}
请注意,这允许传递返回任何类型的指向成员函数的指针。 由于我们并不真正使用返回值,因此我们不关心它是什么。 没有理由强制要求它像您的"解决方法"中那样void
。
使用此方法的唯一缺点是,如果您还打算接受指向声明为 const
的成员函数的指针,则需要两个重载。 完全通用的实现没有此限制。 (我一直希望指向const
成员函数的指针可以隐式转换为指向非const
成员函数的指针,但目前C++不允许这样做。
1 这不是100%正确的。 如果您现在使用完全泛型的类型,则调用方理论上可以传递成员数据指针而不是成员函数指针。 obj.*fp
将评估为对数据成员的引用,然后您将对其调用operator()()
。 只要数据成员的类型实现了此运算符,就可以实例化模板函数GeorgeFunc
。
在 C++17 中,人们可以使用演绎指南来确定类类型和常量,而无需太多样板:
template<bool Const = false, typename R = void, typename C = void, typename... Args> struct MemberFunctionPointerInfoDetail
{
using ClassType = C;
using ReturnType = R;
using Arguments = std::tuple<Args...>;
static constexpr bool isConst = Const;
explicit MemberFunctionPointerInfoDetail(auto){}
};
template<typename R, typename C, typename... Args> MemberFunctionPointerInfoDetail(R(C::**)(Args...)) -> MemberFunctionPointerInfoDetail<false, R, C, Args...>;
template<typename R, typename C, typename... Args> MemberFunctionPointerInfoDetail(R(C::**)(Args...)const) -> MemberFunctionPointerInfoDetail<true, R, C, Args...>;
template<typename mfp> using MemberFunctionPointerInfo = decltype(MemberFunctionPointerInfoDetail((mfp*){}));
您现在可以根据需要使用MemberFunctionPointerInfo<MFPType>::ClassType
。与 ResultType、Argument(作为元组)和 isConst 相同。
void-default 参数有助于防止在推导失败时出现编译器错误。基本上,MemberFunctionPointerInfo<int>
不会导致编译错误,但 ClassType 变为无效。如果需要描述性编译器错误,则可以static_assert此条件。
- QMetaObject invokeMethod的基于函数指针的语法
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- c++r值引用应用于函数指针
- 模板函数指针和lambda
- 是否可以将llvm::FunctionType转换为C/C++原始函数指针
- 带有类的函数指针
- () 函子后面的括号,而不是函数指针?
- 全局作用域中函数指针的赋值
- 使用"Task"函数指针队列定义作业管理器
- 将成员函数指针作为参数传递给模板方法
- 如何创建对象函数指针C++映射?
- 匹配函数指针作为模板参数?
- 通过函数指针定义类范围之外的方法
- 存储在类中的函数指针
- C++从函数指针数组调用函数
- 将返回值存储在函数指针数组的指针中是如何工作的?
- 整数键映射到头文件中的成员函数指针
- 从类成员函数到类 C 函数指针的转换
- 如何将内联匿名函数分配给C++函数指针
- 将字符缓冲区强制转换为函数指针