C++学习---类型萃取---is_const && is_volatile

274 阅读2分钟

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

背景

定义在<type_traits>中,用于判断一个类型是否是const 类型,是否是volatile类型,属于类型的属性识别。

代码实现

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_const

使用模板特化识别带有const修饰的类型即可。

  /// is_const
  template<typename>
    struct is_const
    : public false_type { };

  template<typename _Tp>
    struct is_const<_Tp const>
    : public true_type { };

is_volatile

使用模板特化识别带有volatile修饰的类型即可。

  /// is_volatile
  template<typename>
    struct is_volatile
    : public false_type { };

  template<typename _Tp>
    struct is_volatile<_Tp volatile>
    : public true_type { };

使用案例

#include <iostream>
#include <type_traits>

int main(){
#define LINE(x) std::cout << #x " ?: " << x << "\n"
    std::cout << std::boolalpha;
    std::cout << "------is_const------\n";
    LINE(std::is_const<int>::value);
    LINE(std::is_const<const int>::value);
    LINE(std::is_const<const int*>::value);
    LINE(std::is_const<int* const>::value);
    LINE(std::is_const<const int* const>::value);
    LINE(std::is_const<const int&>::value);
    LINE(std::is_const<const int&&>::value);
    LINE(std::is_const<std::remove_reference<const int&>::type>::value);
    LINE(std::is_const<std::remove_reference<const int&&>::type>::value);
    std::cout << "------is_volatile------\n";
    LINE(std::is_volatile<int>::value);
    LINE(std::is_volatile<volatile int>::value);
    LINE(std::is_volatile<volatile int*>::value);
    LINE(std::is_volatile<int* volatile>::value);
    LINE(std::is_volatile<volatile int* volatile>::value);
    LINE(std::is_volatile<volatile int&>::value);
    LINE(std::is_volatile<volatile int&&>::value);
    LINE(std::is_volatile<std::remove_reference<volatile int&>::type>::value);
    LINE(std::is_volatile<std::remove_reference<volatile int&&>::type>::value);                                                                          
    return 0;
}

const关键字和volatile关键字类似:

  • const关键字说明被修饰的变量只读不可改变
  • volatile关键字说明被修饰的变量在运行过程中可能被改变,使得编译器不能对该变量进行优化

对应上面的测试用例:

  • 形如xxx int*或int xxx *

    • const int*说明该指针指向的变量只读,但该指针可改变,所以并不是const类型
    • volatile int*说明该指针指向的变量不可被优化,但该指针可以被优化,所以并不是volatile类型
  • 形如int* xxx,说明const或volatile是修改这个指针的,这个指针指向的类型为int,所以修饰有效
  • 形如xxx int* xxx,说明const或volatile既修饰指针,又修饰指针指向的变量,修饰有效
  • 对于引用类型(左值引用或右值引用),都是false,原因与xxx int*类似,从右往左解释,这是一个左值/右值引用,引用类型为int,该类型的属性为const或volatile,所以该引用类型不被const或volatile修饰,如果需要判断其类型,则需要使用remove_reference去除引用之后进行判断。

总结

is_const && is_volatile用于判断一个类型是否是const 类型,是否是volatile类型,属于类型的属性识别,需要注意多重修饰的情况,需要仔细辨别const或volatile修饰的主体。