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

std::is_member_pointer 能识别哪些类型
std::is_member_pointer 是一个类型特征(type trait),用于判断某类型是否为「成员指针」——即指向类的非静态成员函数或非静态数据成员的指针。它只对以下两种形式返回 true:
-
ReturnType (ClassType::*)()(成员函数指针) -
Type ClassType::*(成员对象指针)
注意:普通函数指针(如 void(*)())、普通对象指针(如 int*)、nullptr_t、引用、数组、枚举等,全部返回 false。它不关心是否可访问、是否合法(比如私有成员),只做语法层面的类型分类。
如何在编译期做分支判断
结合 std::enable_if_t 或 if constexpr(C++17 起),可在模板中根据是否为成员指针启用不同逻辑。常见于泛型回调包装、反射辅助、序列化元信息提取等场景。
例如,下面这个函数模板仅接受成员指针,并提取其所属类类型:
template<typename t>
auto get_class_of_member_ptr(T ptr) -> std::enable_if_t<:is_member_pointer_v>, typename std::remove_pointer_t<t>::class_type> {
// 实际无法直接取 class_type —— 这里仅为示意结构
// 真实中需借助额外 trait(如自定义 extract_class_t)或宏辅助
}</t></:is_member_pointer_v></typename>
更实用的做法是配合 SFINAE 或概念(C++20)做约束:
template<typename t>
requires std::is_member_pointer_v<t>
void handle_member_ptr(T) {
// 只有成员指针才能进这里
}</t></typename>
常见误判和陷阱
容易混淆的几类情况必须注意:
-
int A::*✅ 是成员指针;但int* A::*❌ 是「指向指针的成员」,仍是成员指针(std::is_member_pointer_v为true) -
decltype(&A::func)✅ 正确获得成员函数指针类型;但&A::func本身是表达式,不能直接传给std::is_member_pointer,必须用decltype -
std::is_member_pointer✅ C++17 起支持带 cv/ref-qualifier 的成员函数指针::value - 空模板参数、未实例化的类模板名(如
A)不能作为std::is_member_pointer的模板实参,会编译失败
完整可运行实例(C++17)
以下代码演示如何用 std::is_member_pointer_v 在编译期区分并处理不同类型:
#include <type_traits>
#include <iostream><p>struct S {
int x = 42;
void f() {}
};</p>
<p>int main() {
static_assert(std::is_member_pointer_v<int s::>>); // true
static_assert(std::is_member_pointer_v<void>)()>); // true
static_assert(!std::is_member_pointer_v<int>>); // false
static_assert(!std::is_member_pointer_v<void>)()>); // false</void></int></void></int></p>
<pre class="brush:php;toolbar:false;">if constexpr (std::is_member_pointer_v<decltype>) {
std::cout ) {
std::cout <p>}</p></decltype>
真正难的不是判断,而是后续怎么从成员指针反推类名或函数签名——std::is_member_pointer 本身不提供这些信息,需要组合 std::remove_pointer、std::is_member_function_pointer、甚至模板偏特化来进一步解构。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











