C++学习---类型萃取---is_void && is_null_pointer

117 阅读2分钟

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

背景

定义在<type_traits>中,用于判断一个类型是否是void类型,是否是nullptr_t类型,属于基础的类型判断。

代码实现

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_void

  template<typename>
    struct __is_void_helper
    : public false_type { }; 

  template<>
    struct __is_void_helper<void>
    : public true_type { }; 

  /// is_void
  template<typename _Tp> 
    struct is_void
    : public __is_void_helper<typename remove_cv<_Tp>::type>::type
    { }; 

这里创建了一个__is_void_helper的辅助类,它的一般版本继承false_type(里面的value值为默认的false值),特化版本接受void参数,继承true_type(value值默认为true值),这就是模板的魅力,通过特化版本直接将void类型识别出来。最后在正式版本中,需要对输入的类型做remove_cv处理,去除掉const和volatile属性,然后再与void进行比较。

is_null_pointer

  template<typename>
    struct __is_null_pointer_helper
    : public false_type { };

  template<>
    struct __is_null_pointer_helper<std::nullptr_t>
    : public true_type { };

  /// is_null_pointer (LWG 2247).
  template<typename _Tp>
    struct is_null_pointer
    : public __is_null_pointer_helper<typename remove_cv<_Tp>::type>::type
    { };

这里的判断方式与is_void是类似的,也是使用了一个模板特化版本,如果类型为std::nullptr_t,则直接继承true_type。同样的也是要使用remove_cv去除const和volatile属性。

使用案例

#include <iostream>
#include <type_traits>

int main(){

    std::cout << std::boolalpha;
    std::cout << "int:\t" << std::is_void<int>::value << std::endl;
    std::cout << "void:\t" << std::is_void<void>::value << std::endl;

    std::cout << "nullptr is null_pointer:\t" << std::is_null_pointer<decltype(nullptr)>::value << std::endl;
    std::cout << "int* is null_pointer:\t" << std::is_null_pointer<int*>::value << std::endl;

    std::cout << "nullptr is pointer:\t" << std::is_pointer<decltype(nullptr)>::value << std::endl;
    std::cout << "int* is pointer:\t" << std::is_pointer<int*>::value << std::endl;                                                                      
    return 0;
}

注意,上面的案例中,我们还检查了nullptr的类型std::nullptr_t是否是空指针,答案是true,但它并不是一个指针,因为在STL中nullptr_t实际上是一个类的定义,可以指向空指针,并不是一个指针类型,所以在判断它是否是指针时,会返回false。

总结

is_void和is_null_pointer分别用来判断一个类型是否是void或std::nullptr_t类型,均使用了模板特化的方法来实现,需要注意到std::nullptr_t是空指针类型,但却不是指针类型,因为它是STL的类实现。