字面量
C/C++一直有字面量这个概念,比如32L是个long、19.0f是float、0x32是16进制整数。
用户自定义字面量
在C++11中,用户可以自定义字面量了,语法上是重载引号运算符实现的,引号后面接个空格,接个下划线,再接用户自定义的符号。
看一个例子,用_C表示一个RGBA的字面量,实例化两个匿名对象出来。
#include <cstdlib>
#include <iostream>
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){}
};
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));
}
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 << "blend " << endl << col1 << col2 << endl;
}
int main() {
blend("r255 g240 b155"_C, "r15 g255 b10 a7"_C);
}
// -std=c++11
/*
blend
r: 255, g: 240, b: 155, a: 0
r: 15, g: 255, b: 10, a: 7
*/
不同类型的规则
虽然重载的符号是引号,但可以支持四种类型,支持的类型是整数、浮点数、字符串、字符。
- 如果字面量是整型数,那么字面量操作符函数只可接受unsigned long long或者const char为其参数。当数太大,unsigned long long无法容纳该字面量的时候,编译器会自动将该字面量转化成以\0为结束符的字符串,用调用以const char为参数的函数版本。
- 如果字面量为浮点型,则字面量操作符函数只可接受long double或者const char为其参数。const char规则跟整形一样,太长的用这个函数。
- 如果字面量为字符串,则字面量操作符只可接受(const char*, size_t)为参数,已知长度的字符串。
- 如果字面量为字符,则字面量操作符只可接受一个char为参数。
函数声明格式
声明字面量操作符函数时,有以下几点需要注意。
- operator ""与用户自定义后缀之间必须有空格。
- 后缀建议以下划线开始,不带下划线时会被编译器警告。
g++实测并没有被警告。
网友评论