开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情
背景
定义在<type_traits>中,用于判断一个类型是否是类的成员对象指针,是否是类的成员函数,属于基础的类型判断。
代码实现
gcc官网:gcc.gnu.org/
gcc代码下载:mirrors.tuna.tsinghua.edu.cn/help/gcc.gi…
gcc版本代码:gcc-7.5.0(branch分支)
文件位置:gcc/libstdc++-v3/include/std/type_traits
注意:以下的代码实现省略了一些宏定义部分,实际的代码还是参考gcc源码,这里仅用作相关原理分析。
实现分析
is_member_object_pointer
使用了一个__is_member_object_pointer_helper,其中的特化版本接受_Tp _Cp::*的类型,其中_Tp代表具体的类型,_Cp::*表示类的成员指针;注意到,这里继承了integral_constant,里面对_Tp进行了判断,因为一个类中除了成员变量就只有成员函数,判断不是函数,那就是变量了,这也是这个判断的原理。同样地,也需要使用remove_cv去除const和volatile属性。
template<typename>
struct __is_member_object_pointer_helper
: public false_type { };
template<typename _Tp, typename _Cp>
struct __is_member_object_pointer_helper<_Tp _Cp::*>
: public integral_constant<bool, !is_function<_Tp>::value> { };
/// is_member_object_pointer
template<typename _Tp>
struct is_member_object_pointer
: public __is_member_object_pointer_helper<
typename remove_cv<_Tp>::type>::type
{ };
is_member_function_pointer
同上面的判断,区别只是反向判断是函数。
template<typename>
struct __is_member_function_pointer_helper
: public false_type { };
template<typename _Tp, typename _Cp>
struct __is_member_function_pointer_helper<_Tp _Cp::*>
: public integral_constant<bool, is_function<_Tp>::value> { };
/// is_member_function_pointer
template<typename _Tp>
struct is_member_function_pointer
: public __is_member_function_pointer_helper<
typename remove_cv<_Tp>::type>::type
{ };
类成员指针的使用
成员指针:数据类型 类名:: *指针名 = &类名::成员名
函数指针:函数返回类型名 (类名::*函数指针名)(参数列表) = &类名::成员函数名
由于类不是运行时 存在的对象。因此,在使用这类指针时,需要首先指定类的一个对象,然后,通过对象来引用指针所指向的成员/函数。
如下:
类对象名.*指向非静态数据成员的指针
类对象指针->*指向非静态数据成员的指针
(类对象名.*指向非静态成员函数的指针)(参数列表)
(类对象指针->*指向非静态成员函数的指针)(参数列表)
#include <iostream>
class A{
public:
int a;
int b;
A(){}
A(int a,int b):a(a),b(b){}
void printAdd(){
std::cout << "a+b=" << a+b << std::endl;
}
};
int main(){
// define member pointer
int A::* pa = &A::a;
int A::* pb = &A::b;
void (A::* pPrintAdd)() = &A::printAdd;
// define object and init pointer
A test;
test.*pa = 3;
test.*pb = 4;
(test.*pPrintAdd)();
return 0;
}
使用案例
#include <iostream>
#include <type_traits>
class A{
public:
int a;
int func(){}
};
int main(){
std::cout << std::boolalpha;
std::cout << "------is_member_object_pointer------" << std::endl;
std::cout << "int (A::*) :" << std::is_member_object_pointer<int (A::*)>::value << std::endl;
std::cout << "A::a :" << std::is_member_object_pointer<decltype(&A::a)>::value << std::endl;
std::cout << "int (A::*)() :" << std::is_member_object_pointer<int (A::*)()>::value << std::endl;
std::cout << "------is_member_function_pointer------" << std::endl;
std::cout << "int (A::*) :" << std::is_member_function_pointer<int (A::*)>::value << std::endl;
std::cout << "A::func :" << std::is_member_function_pointer<decltype(&A::func)>::value << std::endl;
std::cout << "int (A::*)() :" << std::is_member_function_pointer<int (A::*)()>::value << std::endl;
return 0;
}
结果如下所示:分别识别出成员变量指针和成员函数指针。
总结
is_member_object_pointer/is_member_function_pointer分别识别成员变量指针,成员函数指针,成员指针实际上是不完整的指针,只记录了偏移地址,在具体使用时还需要配合实际的对象进行调用。