用户自定义字面量
在实际的开发过程中,我们会经常使用到结构体来表示一个新的类型。那么在遇到结构体类型都数据进行运算时,只能先依次定义,然后进行运行。这在测试环节会非常的繁琐,为此C++11标准增加了可以通过后缀表示的操作符来将字面量转换为需要的类型。
场景案例
例如 我们现在需要使用一个颜色的结构体然后进行合并输出的一个操作,那么实现大概是下面这个样子:
#include <iostream> #include <cstdlib> using namespace std; typedef unsigned char uint8; struct RGBA { uint8 r; uint8 g; uint8 b; uint8 a; RGBA(uint8 R, uint8 G, uint8 B, uint8 A = 0) :r(R),g(G),b(B),a(A){} }; std::ostream& operator<< (std::ostream& out, RGBA& col) { return out << "r: " << (int)col.r << ", g: " << (int)col.g << ", b: " << (int)col.b << ", a: " << (int)col.a << endl; } void blend(RGBA& col1, RGBA& col2) { cout << __func__ << endl << col1 << col2 << endl; } int main() { RGBA col1(255, 255, 255); // C++98 初始化 RGBA col2{ 10, 22, 65, 5 }; // C++11 初始化列表 blend(col1, col2); // 进行运算 return 0; }
运行结果:
blend r: 255, g: 255, b: 255, a: 0 r: 10, g: 22, b: 65, a: 5
很明显当我需要进行运算时,必须先依次对变量进行创建,能不能直接传常量到blend函数中呢?C++11就可以做到,后缀标识符配合右值引用完美解决这个问题。
C++11使用后缀标识符解析字符串
主要的改动就是需要添加下面这个函数,这个函数的主要功能就是通过解析标识符来定位对应的指针,然后将字符串转换为整型的一个思路。
RGBA operator""_C(const char* col, size_t n) { const char* p = col; const char* end = col + n; const char* r, * g, * b, * a; r = g = b = a = nullptr; for (; p != end; ++p) { if(*p == 'r') { r = p; } else if(*p == 'g') { g = p; } else if(*p == 'b') { b = p; } else if(*p == 'a') { a = p; } } if(r == nullptr || g == nullptr || b == nullptr) { throw; } else if(a == nullptr) { return RGBA(atoi(r + 1), atoi(g + 1), atoi(b + 1)); } else { return RGBA(atoi(r + 1), atoi(g + 1), atoi(b + 1), atoi(a + 1)); } }
然后因为我们需要输入字面常量,所以我们的blend函数的参数就需要将左值引用改成右值引用。
void blend(RGBA&& col1, RGBA&& col2) { cout << __func__ << endl << col1 << col2 << endl; }
在调用方面也从之前的三行压缩为一行,更加简洁、优雅。
int main() { blend("r255 g240 b155"_C, "r15 g255 b10 a7"_C); return 0; }
C++11使用后缀标识符解析数字
对应不同类型的字面量还有着相应的限制,就比如整型类型字面量的参数只能是unsigned long long
或者 const char*
。我将在最后对各个类型的要求做一个总结。
#include <iostream> #include <cstdlib> using namespace std; struct T { public: int t; }; T operator""_t(unsigned long long t) { return { static_cast<int>(t) }; } int main() { T t = 1111_t; return 0; }
字面量规则
字面量类型 | 参数要求 | 说明 |
整型 | unsigned long long or const char* |
当unsigned long long 类型无法容纳下该字面量时,编译器会自动将字面量转换为以\0 结束的字符串,并调用const char* 参数版本的函数来处理 |
浮点型 | long double or const char* |
和整型的处理相同,long double 容纳不下时,编译器会自动将字面量转换为以\0 结束的字符串,并调用const char* 参数版本的函数来处理 |
字符串 | (const char*, size_t) |
只有一种写法 |
字符 | char |
只有一种写法 |
注意
- 后缀建议以
_
下划线这种格式。