c++新特性实验(2)类型特性
1. 基本类型
1.1 增加
long long long long int signed long long signed long long int unsigned long long unsigned long long int |
至少 64 位的宽度 | C++11 |
char8_t | UTF-8 字符类型 | C++20 |
char16_t | UTF-16 字符类型 | C++11 |
char32_t | UTF-32 字符类型 | C++11 |
1.2 修改char的符号(C++14)
char 的符号取决于编译器和目标平台:
- ARM 和 PowerPC 的默认设置常为无符号,
- 而 x86 与 x64 的默认设置常为有符号。
1.3 示例
1 #include <cstdlib> 2 #include <cstdio> 3 4 int 5 main(int argc,char *argv[]){ 6 7 unsigned long long ull = 100; 8 unsigned long long int ulli = 100; 9 signed long long sll = 100; 10 signed long long int slli = 100; 11 12 long long ll = 100; 13 long long int lli = 100; 14 15 printf("unsigend long long = %ld \n",sizeof ++ull); 16 printf("ull = %ld \n",ull); 17 18 19 char16_t ch16 = u'\u5b89'; 20 char32_t ch32 = U'\u5353'; 21 printf("ch16 = %c ,char32 = %c \n",ch16,ch32); 22 23 return 0; 24 }
2.固定字节数的整形类型(C++11 起)
定义于头文件 <cstdint>
int8_t,int16_t,int32_t,int64_t | 分别为宽度恰为 8、16、32 和 64 位的有符号整数类型 |
int_fast8_t,int_fast16_t,int_fast32_t,int_fast64_t, | 分别为宽度至少有 8、16、32 和 64 位的最快的有符号整数类型 |
int_least8_t,int_least16_t,int_least32_t,int_least64_t | 分别为宽度至少有 8、16、32 和 64 位的最小的有符号整数类型 |
intmax_t,uintmax_t | 最大宽度的有符号整数类型和无符号整数类型 |
intptr_t,uintptr_t | 足以保存指针的有符号整数类型和无符号整数类型 |
uint8_t,uint16_t,uint32_t,uint64_t | 宽度恰为 8、16、32 和 64 位的无符号整数类型. |
uint_fast8_t,uint_fast16_t,uint_fast32_t,uint_fast64_t | 分别为宽度至少有 8、16、32 和 64 位的最快无符号整数类型 |
uint_least8_t,uint_least16_t,uint_least32_t,uint_least64_t | 分别为宽度至少有 8、16、32 和 64 位的最小无符号整数类型 |
3.基本类型宏(C++11 起)
定义于头文件 <cstddef>
nullptr_t,nullptr | 空指针字面量. | C++11 |
max_align_t | 具有不小于任何基础类型的内存对齐需求的平凡类型 | C++11 |
byte
|
字节类型 ,它在std::下。 | C++17 |
__bool_true_false_are_defined
|
C 兼容用宏常量,展开成整数常量1 | C++11 |
__alignas_is_defined
|
C 兼容用宏常量,展开成整数常量 1 | C++11 |
4.类型特性(C++11 起)
类型特性用以查询或修改类型的属性,通常在模板中使用.
定义于头文件 <type_traits>
4.1 基础类型类别
is_void
|
检查类型是否为 void |
C++11 |
is_null_pointer
|
检查类型是否为 std::nullptr_t |
C++14 |
is_integral
|
检查类型是否为整型 | C++11 |
is_floating_point
|
检查类型是否是浮点类型 | C++11 |
is_array
|
检查类型是否是数组类型 | C++11 |
is_enum
|
检查类型是否是枚举类型 | C++11 |
is_union
|
检查类型是否为联合体类型 | C++11 |
is_class
|
检查类型是否非联合类类型 | C++11 |
is_function
|
检查是否为函数类型 | C++11 |
is_pointer
|
检查类型是否为指针类型 | C++11 |
is_lvalue_reference
|
检查类型是否为左值引用 | C++11 |
is_rvalue_reference
|
检查类型是否为右值引用 | C++11 |
is_member_object_pointer
|
检查类型是否为指向非静态成员对象的指针 | C++11 |
is_member_function_pointer
|
检查类型是否为指向非静态成员函数的指针 | C++11 |
4.2 复合类型类别
is_fundamental
|
检查是否是基础类型 | C++11 |
is_arithmetic
|
检查类型是否为算术类型 | C++11 |
is_scalar
|
检查类型是否为标量类型 | C++11 |
is_object
|
检查是否是对象类型 | C++11 |
is_compound
|
检查是否为复合类型 | C++11 |
is_reference
|
检查类型是否为左值引用或右值引用 | C++11 |
is_member_pointer
|
检查类型是否为指向非静态成员函数或对象的指针类型 | C++11 |
4.3 类型属性、类型关系、受支持操作
参看:http://en.cppreference.com/w/cpp/types
4.4示例
1 #include <type_traits> 2 #include <cstddef> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <cstdint> 6 7 using namespace std; 8 9 class student{ 10 public: 11 byte age; 12 public: 13 student(byte _age):age(_age){ 14 15 } 16 student(){ 17 student((byte)23); 18 } 19 }; 20 21 template<typename T> 22 void 23 fun(T const &t){ 24 printf("\n-------==============------------=====-----------\n"); 25 printf("t = %d\n",t); 26 printf("t.is_void = %d\n" ,is_void<T>::value ); 27 printf("t.is_integral = %d\n" ,is_integral<T>::value ); 28 printf("t.is_null_pointer = %d\n" ,is_null_pointer<T>::value ); 29 printf("t.is_pointer = %d\n" ,is_pointer<T>::value ); 30 printf("t.is_class = %d\n" ,is_class<T>::value ); 31 printf("t.is_lv_reference = %d\n" ,is_lvalue_reference<T>::value); 32 printf("t.is_array = %d\n" ,is_array<T>::value); 33 if(is_array<T>::value){ 34 printf("t.rank = %ld\n" ,rank<T>::value); 35 } 36 } 37 38 //template<typename U> 39 void fun(nullptr_t null){ 40 } 41 42 template<typename F, typename A> 43 void 44 funfwd(F _fun, A _arg) 45 { 46 _fun(_arg); 47 } 48 49 void 50 g(int* i){ 51 printf("function g called \n"); 52 } 53 54 int 55 main(int argc,char *argv[]){ 56 byte age = (byte)1; 57 int8_t int8[] = {1,2,3,4}; 58 int64_t int64 = 64, &refInt64 = int64; 59 int_fast64_t *pFastInt64 = &int64; 60 nullptr_t nullp; 61 62 63 byte *pb = &age; 64 student s = {age}; 65 printf("s.age = %d\n",s.age); 66 67 fun(100); 68 fun<student>(s); 69 //fun<void>(1); 70 fun(pFastInt64); 71 fun(int8); 72 fun(refInt64); 73 fun(nullp); 74 75 g(NULL); // ok 76 g(0); // ok 77 funfwd(g, nullptr); // ok 78 //funfwd(g, NULL); // error:NULL是个宏,值是0,这里展开后不存在函数 g(int) 79 80 return 0; 81 }
4.5类型修改
remove_cv
|
从给定类型移除 const 或/与 volatile 限定符 |
C++11 |
remove_const
|
||
remove_volatile
|
||
add_cv
|
添加 const 或/与 volatile 限定符到给定类型 |
C++11 |
add_const
|
||
add_volatile
|
||
remove_reference
|
从给定类型移除或者添加引用 | C++11 |
add_lvalue_reference
add_rvalue_reference
|
||
remove_pointer | 移除给定类型的一级指针 | C++11 |
add_pointer | 对给定类型添加一级指针 | C++11 |
示例
1 #include <cstdio> 2 #include <cstdlib> 3 #include <type_traits> 4 5 using namespace std; 6 7 8 template<typename T> 9 void 10 fun(const T &t){ 11 printf("t is const = %d\n",is_const<T>::value); 12 13 typedef remove_cv<const int>::type type1; 14 15 } 16 17 int 18 main(int argc,char *argv[]){ 19 20 const int a = 100; 21 fun(100); 22 23 typedef remove_cv<const int>::type type1; 24 typedef remove_cv<volatile int>::type type2; 25 typedef remove_cv<const volatile int>::type type3; 26 typedef remove_cv<const volatile int*>::type type4; 27 typedef remove_cv<int * const volatile>::type type5; 28 29 printf("test1 : %s \n" ,(is_same<int, type1>::value ? "passed" : "failed" )); 30 printf("test2 : %s \n" ,(is_same<int, type2>::value ? "passed" : "failed" )); 31 printf("test3 : %s \n" ,(is_same<int, type2>::value ? "passed" : "failed" )); 32 printf("test4 : %s \n" ,(is_same<const volatile int*, type4>::value ? "passed" : "failed" )); 33 printf("test5 : %s \n" ,(is_same<int*, type5>::value ? "passed" : "failed" )); 34 35 36 37 return 0; 38 }
5.字面类型(C++11 起)
5.1 哪些类型是字面类型
- 标量类型;
- 引用类型;
- 字面类型的数组;
- 可为 cv 限定的 void (从而 constexpr 函数能返回 void )(C++14 起);
- 可有 cv 限定的类类型,并拥有下列全部约束:
-
-
- 拥有析构函数,
- 满足以下条件之一
- 聚合类型
- 或拥有至少一个 constexpr 构造函数(可为模板)且非复制或移动构造函数
- 或为闭包类型 (C++17 起)
-
- 对于联合体,至少有一个非静态数据成员是非 volatile 字面类型,
- 对于非联合体,所有非静态数据成员和基类是非 volatile 字面类型。
- 所有非静态数据成员和基类是非 volatile 字面类型。
-
5.2 示例
1 #include <stdexcept> 2 #include <cstdlib> 3 #include <cstdio> 4 5 using namespace std; 6 7 class conststr{ 8 public: 9 const char* p; 10 size_t sz; 11 template<size_t N> 12 constexpr conststr(const char(&a)[N]) : p(a), sz(N - 1) {} 13 14 constexpr char operator[](size_t n) const { 15 return n < sz ? p[n] : throw out_of_range(""); 16 } 17 constexpr size_t size() const { return sz; } 18 }; 19 20 constexpr size_t countlower(conststr s, size_t n = 0,size_t c = 0){ 21 return n == s.size() ? c : s[n] >= 'a' && s[n] <= 'z' ? countlower(s, n + 1, c + 1) : countlower(s, n + 1, c); 22 } 23 24 // 要求编译时常量的输出函数,为测试用 25 template<int n> 26 struct constN{ 27 constN() { 28 printf("n = %d \n",n); 29 } 30 }; 31 32 int 33 main(int argc,char *argv[]){ 34 constN<countlower("Hello, world!")>(); // 隐式转换成 conststr 35 return 0; 36 }