c++中如何使用std::is_member_pointer判断成员指针_c++类型萃取【实例】

11次阅读

std::is_member_pointer仅对成员函数指针(如ReturnType (ClassType::)())和成员对象指针(如Type ClassType::)返回true,其余类型均返回false。

c++中如何使用std::is_member_pointer判断成员指针_c++类型萃取【实例】

std::is_member_pointer 能识别哪些类型

std::is_member_pointer 是一个类型特征(type trait),用于判断某类型是否为「成员指针」——即指向类的非静态成员函数或非静态数据成员的指针。它只对以下两种形式返回 true

  • ReturnType (ClassType::*)()(成员函数指针)
  • Type ClassType::*(成员对象指针)

注意:普通函数指针(如 void(*)())、普通对象指针(如 int*)、nullptr_t、引用、数组、枚举等,全部返回 false。它不关心是否可访问、是否合法(比如私有成员),只做语法层面的类型分类。

如何在编译期做分支判断

结合 std::enable_if_tif constexprc++17 起),可在模板中根据是否为成员指针启用不同逻辑。常见于泛型回调包装、反射辅助、序列化元信息提取等场景。

例如,下面这个函数模板仅接受成员指针,并提取其所属类类型:

立即学习C++免费学习笔记(深入)”;

template auto get_class_of_member_ptr(T ptr) -> std::enable_if_t, typename std::remove_pointer_t::class_type> {     // 实际无法直接取 class_type —— 这里仅为示意结构     // 真实中需借助额外 trait(如自定义 extract_class_t)或宏辅助 }

更实用的做法是配合 SFINAE 或概念(C++20)做约束:

template requires std::is_member_pointer_v void handle_member_ptr(T) {     // 只有成员指针才能进这里 }

常见误判和陷阱

容易混淆的几类情况必须注意:

  • int A::* ✅ 是成员指针;但 int* A::* ❌ 是「指向指针的成员」,仍是成员指针(std::is_member_pointer_vtrue
  • decltype(&A::func) ✅ 正确获得成员函数指针类型;但 &A::func 本身是表达式,不能直接传给 std::is_member_pointer,必须用 decltype
  • std::is_member_pointer::value ✅ C++17 起支持带 cv/ref-qualifier 的成员函数指针
  • 空模板参数、未实例化的类模板名(如 A)不能作为 std::is_member_pointer 的模板实参,会编译失败

完整可运行实例(C++17)

以下代码演示如何用 std::is_member_pointer_v 在编译期区分并处理不同类型:

#include  #include  

struct S { int x = 42; void f() {} };

int main() { static_assert(std::is_member_pointer_v>); // true static_assert(std::is_member_pointer_v)()>); // true static_assert(!std::is_member_pointer_v>); // false static_assert(!std::is_member_pointer_v)()>); // false

if constexpr (std::is_member_pointer_vzuojiankuohaophpcndecltype(&S::x)youjiankuohaophpcn) {     std::cout zuojiankuohaophpcnzuojiankuohaophpcn "S::x is a data member pointern"; }  if constexpr (std::is_member_pointer_vzuojiankuohaophpcndecltype(&S::f)youjiankuohaophpcn) {     std::cout zuojiankuohaophpcnzuojiankuohaophpcn "S::f is a member function pointern"; }

}

真正难的不是判断,而是后续怎么从成员指针反推类名或函数签名——std::is_member_pointer 本身不提供这些信息,需要组合 std::remove_pointerstd::is_member_function_pointer、甚至模板偏特化来进一步解构。

text=ZqhQzanResources