杂货边角(21):用户自定义字面量 operator "" _X
2018-02-25 15:55
288 查看
在C++编程中,用户自定义类或结构体是难以避免的事情,所以一旦遇到接受用户自定义的类或结构体作为参数的函数,那么必然难逃”先初始化变量–变量传值或传引用调用函数“,这就导致了编程过程中出现的不直观。
正所谓没有对比就没有伤害,为什么对于
这便是字面量的威力,可以直接更加直观的字符串信息进行隐式的类型转换和函数调用,从而使得逻辑更为直观。那么用户自定义的类是否也可以实现这种通过字面量直接进行参数传递的效果呢?答案在C++11是肯定的。这便是
自定义字面量的限制:
1. 如果字面量是字符串,那么字面量操作符函数只能接受
2. 如果目标字面量的形式是整数型,那么字面量操作符函数只能接受
3. 如果目标字面量的形式是浮点数型,那么字面量操作符函数只能接受
4. 如果目标字面量为
此外需要额外注意的是:
struct T {...}; void func(T t1, T t2) {...} ... T temp1(xxxx); T temp2(xxxx); func(temp1, temp2);
正所谓没有对比就没有伤害,为什么对于
void func(int , double)可以直接使用
func(12, 3.14)调用,而不用
int a = 12; double b = 3.14; func(a, b);
这便是字面量的威力,可以直接更加直观的字符串信息进行隐式的类型转换和函数调用,从而使得逻辑更为直观。那么用户自定义的类是否也可以实现这种通过字面量直接进行参数传递的效果呢?答案在C++11是肯定的。这便是
operator "" _X字面量操作符函数的引入。
#include <iostream> #include <cstdlib> #include <cstring> 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)函数会主动解析以_C为后缀的字符串,并返回一个RGBA右值对象 RGBA operator "" _C(const char* col, size_t n){ cout << "This round target content:" << static_cast<string>(col) << " with char-num:" << n << endl; 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; } //这里的blend函数形参是右值引用,是专门为RGBA字面量化设计的,普通的RGBA对象是无法调用的 void blend(RGBA && col1, RGBA && col2) { cout << "rvluae version blend" << endl << col1 << col2 << endl; } //函数重载,这里是可以接受正常左值类型参数的函数入口 void blend(RGBA& col1, RGBA& col2) { cout << "lvluae version blend" << endl << col1 << col2 << endl; } int main() { /*传统逻辑下,需要至少三行代码才能搞定一次blend测试*/ RGBA col1(255, 240, 155); RGBA col2(15, 255, 10, 7); blend(col1, col2); /*定义了字面量操作符函数后,只需要一句代码即可搞定*/ blend("r255 g240 b155"_C, "r15 g255 b10 a7"_C); return 0; }
自定义字面量的限制:
1. 如果字面量是字符串,那么字面量操作符函数只能接受
const char*, size_t为参数,系统会主动对字符串进行解析,并完成形参赋值匹配;
2. 如果目标字面量的形式是整数型,那么字面量操作符函数只能接受
unsigned long long或
const char*为其参数,当
unsigned long long溢出后,编译器会自动切换到
const char*版本;
3. 如果目标字面量的形式是浮点数型,那么字面量操作符函数只能接受
long double或
const char*为其参数,规则同2;
4. 如果目标字面量为
char,那么字面量操作符函数只可接受一个
char为参数
此外需要额外注意的是:
operator "" _X中的
_X中下划线不是标准规定的,但是为避免混乱,下划线最好带上;
X中X则可以根据需求自己修改,如上面采用的C。
相关文章推荐
- 实现一个"可变二维数组",这个二维数组的行数要求用户从键盘输入,每行的元素个数仍由用户从键盘输入. //数组元素值用户可以自定义.最后把二维数组打印出来.不要忘记释放数组内存. /*void main
- c#实现隐式的用户自定义类型转换(关键字implicit operator)
- DIY一个C++ traits来判断enum是否有用户自定义的operator<<
- 自定义std::sort的比较函数时发生"invalid operator<"错误原因
- UI一揽子计划 21 (UICollectionView、SDWebImage第三方类库加载图片的使用、集合视图的布局UICollectionViewFlowLayout 、自定义Cell、布局协议
- GridView 后台排列 Column 、 用户自定义GridView 显示、GridView的PreRender ,Init,Load 方法
- php usort 使用用户自定义的比较函数对二维数组中的值进行排序
- shell脚本报错:"[: =: unary operator expected"
- 禁止在 .NET Framework 中执行用户代码。启用 "clr enabled" 配置选项
- 用户验证之自定义身份验证
- 执行用户定义例程或聚合 "" 期间出现 .NET Framework 错误:
- 在oracle中判定一个用户自定义对象是否存在
- 用户自定义文件的元数据
- "ORA-01940: 无法删除当前已连接的用户"的解决方法
- 禁止在 .NET Framework 中执行用户代码。启用 \"clr enabled\ SQL开启CLR
- 了解--Dashboard Android用户自定义UI设计模板
- js代码实现根据实际物理地址,进行 URL 跳转,并实现用户自定义 URL 跳转
- shell切换用户EOF下变量的使用[: ==: unary operator expected
- ReturnType operator "" _suffix(Type t){Method's Body}
- 用户收到"无法显示页面"的错误消息和"Connections_refused"条目记录在正在运行 Windows Server 2003,Exchange 2003 中,IIS 6.0 的服务器上的 Httperr.log 文件