std::is_member_function_pointer 用于判断类型是否为「非静态成员函数指针」,仅接受干净的类型名(如 decltype(f)),不接受表达式、普通函数指针、lambda、成员变量指针、static 成员函数指针或 nullptr。

std::is_member_function_pointer 用来判断什么类型
它只判断一个类型是不是「非静态成员函数指针」,不接受普通函数指针、lambda、成员变量指针、static 成员函数指针,也不接受 nullptr 或表达式——只接受类型名(比如 decltype(f) 的结果)。
常见误用是传入 &Class::func 这样的值:这本身是表达式,类型推导后可能带 cv 限定符或引用,但 std::is_member_function_pointer 检查的是「类型是否匹配模板特化」,所以必须确保传的是干净的类型名。
- ✅ 正确:
std::is_member_function_pointer_v<decltype></decltype> - ❌ 错误:
std::is_member_function_pointer_v(语法非法) - ⚠️ 易错:
std::is_member_function_pointer_v<decltype>(&A::foo))></decltype>—— 强制转换可能掩盖 const/volatile 修饰,导致判断为 false
为什么 &Class::func 的类型不总是 member function pointer
取地址操作符 & 作用于成员函数时,结果类型取决于函数声明细节。例如:
struct X {
void f() const;
void g() &;
void h() &&;
};
&X::f 类型是 void (X::*)() const,属于 member function pointer;但若函数被重载,&X::g 在某些上下文中可能被解释为函数类型(而非指针),此时 decltype 推出的是函数类型,而 std::is_member_function_pointer 对函数类型返回 false。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 成员函数指针类型必须显式含
X::*语法结构 - const / volatile / ref-qualifier 都会成为类型一部分,不影响判定结果
- static 成员函数(如
static void s();)的&X::s是普通函数指针类型,std::is_member_function_pointer返回false
在 SFINAE 和 concept 中怎么安全使用
直接在模板参数约束中用 std::is_member_function_pointer_v<t></t> 是可行的,但要注意别让 T 是未定义行为的类型(比如 void、数组、引用类型)。更稳妥的做法是先用 std::is_class_v<:remove_pointer_t>::class_type></:remove_pointer_t> 配合,不过通常没必要——标准库特化已覆盖所有合法成员函数指针类型。
- ✅ 安全的 SFINAE 示例:
template<typename t> auto call_if_mem_fn(T p) -> std::enable_if_t<:is_member_function_pointer_v>, int> { return 42; }</:is_member_function_pointer_v></typename> - ✅ C++20 concept 写法:
template<typename t> concept is_member_fn_ptr = std::is_member_function_pointer_v<t>;</t></typename>
- ⚠️ 注意:不要对
T*或T&做判定——std::is_member_function_pointer_v<int></int>是 false,但std::is_member_function_pointer_v<int></int>才是 true
和 std::is_member_pointer 的关键区别
std::is_member_pointer 是父类判断:只要是指向类成员的指针(无论函数还是变量),都返回 true;而 std::is_member_function_pointer 是子集限定,只对「指向非静态成员函数」的指针类型返回 true。
-
int X::*→std::is_member_pointer_v<int x::> == true</int>,但std::is_member_function_pointer_v<int x::> == false</int> -
void (X::*)()→ 两者都为 true -
void (X::*)() const noexcept→ 仍属于 member function pointer,noexcept不影响判定 - 实际项目中,如果只想过滤掉成员函数调用场景(比如绑定器、反射元编程),必须用
std::is_member_function_pointer,不能退化为std::is_member_pointer
真正容易被忽略的是:这个 trait 不做任何运行时检查,也不关心该指针是否可调用、是否有访问权限、是否来自多继承虚基类——它只回答“这个类型在语言层面是不是标准定义的成员函数指针类型”。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










