C++11之用户自定义字面量(ClassType operator““_C(param...))

简介: C++11之用户自定义字面量(ClassType operator““_C(param...))

用户自定义字面量

在实际的开发过程中,我们会经常使用到结构体来表示一个新的类型。那么在遇到结构体类型都数据进行运算时,只能先依次定义,然后进行运行。这在测试环节会非常的繁琐,为此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 只有一种写法


注意

  • 后缀建议以_下划线这种格式。
目录
相关文章
|
6月前
|
C语言 C++
C/C++ 自定义头文件,及头文件结构详解
还是从"stdio.h"说起,这是C语言中内置的标准库,也就是说,头文件很多时候其实就是一个“库”,类似于代码的仓库,也就是说将某些具有特定功能的常量、宏、函数等归为一个大类,然后放进这个“仓库”,就像stdio.h就是一个标准输入/输出的头文件
204 1
|
6月前
|
存储 算法 数据库
【C++ 软件设计思路】学习C++中如何生成唯一标识符:从UUID到自定义规则
【C++ 软件设计思路】学习C++中如何生成唯一标识符:从UUID到自定义规则
345 0
|
6月前
|
存储 算法 C语言
【C++ 迭代器实现 终篇】深入理解C++自定义容器和迭代器的实现与应用
【C++ 迭代器实现 终篇】深入理解C++自定义容器和迭代器的实现与应用
223 0
|
6月前
|
存储 缓存 并行计算
C/C++ 数据结构设计与应用(二):自定义数据结构的设计 (Design of Custom Data Structures)
C/C++ 数据结构设计与应用(二):自定义数据结构的设计 (Design of Custom Data Structures)
117 0
|
3月前
|
C++
C++ PCL 沿着自定义的平面做横截面(直通滤波)
C++ PCL 沿着自定义的平面做横截面(直通滤波)
44 0
|
6月前
|
程序员 编译器 C++
C++中的运算符重载(Operator Overloading)
C++中的运算符重载(Operator Overloading)
58 1
|
2月前
|
C++
C++(十)operator=
本文档介绍了 C++ 中赋值运算符 `operator=` 的重载方法,包括其概念、语法格式及特性,并通过实现一个 `mystring` 类展示了具体的代码示例。赋值运算符用于将一个已创建的对象赋值给另一个已创建的对象,需注意自赋值、内存泄漏和重析构等问题。文档中的 `mystring` 类实现了字符串对象的赋值、拼接及比较等功能。
|
6月前
|
算法 网络协议 编译器
【C++ 14 新特性】C++14二进制字面量:深度探索与实践
【C++ 14 新特性】C++14二进制字面量:深度探索与实践
132 1
|
4月前
|
NoSQL 编译器 Redis
c++开发redis module问题之如果Redis加载了多个C++编写的模块,并且它们都重载了operator new,会有什么影响
c++开发redis module问题之如果Redis加载了多个C++编写的模块,并且它们都重载了operator new,会有什么影响
|
3月前
|
C++ 容器
C++中自定义结构体或类作为关联容器的键
C++中自定义结构体或类作为关联容器的键
40 0