C++学习---类型萃取---is_pointer && is_lvalue_reference/is_rvalue_reference

140 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

背景

定义在<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_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; 
}

从上面的案例中可以看出:

  • 数组int[10]并不是指针类型,但是平时的编码中我们可以将数组名当做指针使用;
  • std::nullptr_t并不是指针类型,只是STL实现的一个类,用于表示空指针。

总结

is_pointer && is_lvalue_reference/is_rvalue_reference用于判断一个类型是否是指针类型,是否是左值引用类型/右值引用类型,使用了模板特化的原理实现,其中注意指针类型中,类似int[10]的数组或std::nullptr_t并不是指针类型。