开启掘金成长之旅!这是我参与「掘金日新计划 · 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修饰的主体。