背景
定义在<type_traits>中,用于判断一个类型是否是指针类型,是否是左值引用类型/右值引用类型,属于基础的类型判断。
代码实现
gcc 官网:https://gcc.gnu.org/
gcc 代码下载:https://mirrors.tuna.tsinghua.edu.cn/help/gcc.git/
gcc 版本代码:gcc-7.5.0(branch 分支)
文件位置:gcc/libstdc++-v3/include/std/type_traits
注意:以下的代码实现省略了一些宏定义部分,实际的代码还是参考 gcc 源码,这里仅用作相关原理分析。
实现分析
is_pointer
使用模板特化识别_TP*,最后识别之前使用 remove_cv 去除 const 和 volatile 属性。这个方法比较简单,也很容易理解。
template<typename>
struct __is_pointer_helper
: public false_type { };
template<typename _Tp>
struct __is_pointer_helper<_Tp*>
: public true_type { };
/// is_pointer
template<typename _Tp>
struct is_pointer
: public __is_pointer_helper<typename remove_cv<_Tp>::type>::type
{ };
复制代码
is_lvalue_reference
使用模板特化识别_Tp&,返回 true,其他情况均为 false.
/// is_lvalue_reference
template<typename>
struct is_lvalue_reference
: public false_type { };
template<typename _Tp>
struct is_lvalue_reference<_Tp&>
: public true_type { };
复制代码
is_rvalue_reference
使用模板特化识别_Tp&&,返回 true,其他情况均为 false.
/// is_rvalue_reference
template<typename>
struct is_rvalue_reference
: public false_type { };
template<typename _Tp>
struct is_rvalue_reference<_Tp&&>
: public true_type { };
复制代码
使用案例
#include <iostream>
#include <type_traits>
struct PointerTest{};
struct A{};
int main(){
std::cout << std::boolalpha;
std::cout <<"------is_pointer------\n";
std::cout << "int[10]:" << std::is_pointer<int[10]>::value << std::endl;
std::cout << "nullptr_t:" << std::is_pointer<std::nullptr_t>::value << std::endl;
std::cout << "int*:" << std::is_pointer<int*>::value << std::endl;
std::cout << "int**:" << std::is_pointer<int**>::value << std::endl;
std::cout << "int&:" << std::is_pointer<int&>::value << std::endl;
std::cout << "const volatile int*:" << std::is_pointer<const volatile int*>::value << std::endl;
std::cout << "PointerTest*:" << std::is_pointer<PointerTest*>::value << std::endl;
std::cout <<"------is_lvalue_reference/is_rvalue_reference------\n";
std::cout << "int&:" << std::is_lvalue_reference<int&>::value << std::endl;
std::cout << "int&&:" << std::is_lvalue_reference<int&&>::value << std::endl;
std::cout << "A&:" << std::is_lvalue_reference<A&>::value << std::endl;
std::cout << "A&&:" << std::is_lvalue_reference<A&&>::value << std::endl;
std::cout <<"------is_rvalue_reference------\n";
std::cout << "int&:" << std::is_rvalue_reference<int&>::value << std::endl;
std::cout << "int&&:" << std::is_rvalue_reference<int&&>::value << std::endl;
std::cout << "A&:" << std::is_rvalue_reference<A&>::value << std::endl;
std::cout << "A&&:" << std::is_rvalue_reference<A&&>::value << std::endl;
return 0;
}
复制代码
从上面的案例中可以看出:
总结
is_pointer && is_lvalue_reference/is_rvalue_reference 用于判断一个类型是否是指针类型,是否是左值引用类型/右值引用类型,使用了模板特化的原理实现,其中注意指针类型中,类似 int[10]的数组或 std::nullptr_t 并不是指针类型。
评论