C++11 用户自定义数据标识

本文根据众多互联网博客内容整理后形成,引用内容的版权归原始作者所有,仅限于学习研究使用,不得用于任何商业用途。

用户定义数据标识(User-defined literals)

C++提供了许多内建数据类型的数据标识(2.14节变量):

123    // int整型
1.2    // double双精度型
1.2F    // float浮点型
’a'    // char字符型
1ULL    // unsigned long long64位无符号长整型
0xD0    // hexadecimal unsigned十六进制无符号整型
"as"    // string字符串

但是在C++98中并没有为用户自定义的变量类型提供数据标识。这就违反甚至冲突于“用户自定类型应该和内建类型一样得到支持”的原则。在特殊情况下,人们有以下的需求:

"Hi!"s            //字符串,不是“以零字符为终结的字符数组”
1.2i            //虚数
123.4567891234df    //十进制浮点型(IBM)
101010111000101b    //二进制
123s            //秒
123.56km          //不是英里(单位)
1234567890123456789012345678901234567890x        //扩展精度

C++11通过在变量后面加上一个后缀来标定所需的类型以支持“用户定义数据标识”,自字义后缀用operator""定义,就是一种特殊的函数。后缀名必须以下划线开头,因为没有下划线的后缀是留给std用的。后缀的参数只能是unsigned long long、long double、const char或者const char + size_t。没了,它就是这么简单易上手又很实用的特性。一般来说适合编为后缀的是单位,如kg,km。例如:

constexpr complex operator "" i(long double d)    // 设计中的数据标识
{
    return {0,d};    //complex是一个数据标识
}

// 将n个字符构造成字符串std::string对象的数据标识
std::string operator""s (const char* p, size_t n)    
{
    return string(p,n);    // 需要释放存储空间
}

这里需要注意的是,constexpr的使用可以进行编译时期的计算。使用这一功能,我们可以这样写:

template <class T> void f(const T&);
f("Hello");    // 传递char*指针给f()
f("Hello"s);    // 传递(5个字符的)字符串对象给f()
f("Hello n"s);    // 传递(6个字符的)字符串对象给f()

auto z = 2+1i;    // 复数complex(2,1)

基本(实现)方法是编译器在解析什么语句代表一个变量之后,再分析一下后缀。用户自定义数据标识机制只是简简单单的允许用户制定一个新的后缀,并决定如何对它之前的数据进行处理。要想重新定义一个内建的数据标识的意义或者它的参数、语法是不可能的。一个数据标识操作符可以使用它(前面)的数据标识传递过来的处理过的值(如果是使用新的没有定义过的后缀的值)或者没有处理过的值(作为一个字符串)。

要得到一个没有处理过的字符串,只要使用一个单独的const char*参数即可,例如:

Bignum operator"" x(const char* p)
{
    return Bignum(p);
}

void f(Bignum);
f(1234567890123456789012345678901234567890x);

这个C语言风格的字符串”1234567890123456789012345678901234567890″被传递给了操作符 operator”” x()。注意,我们并没有明确地把数字转换成字符串。

有以下四种数据标识的情况,可以被用户定义后缀来使用用户自定义数据标识:

  • 整型标识:允许传入一个unsigned long long或者const char*参数
  • 浮点型标识:允许传入一个long double或者const char*参数
  • 字符串标识:允许传入一组(const char*,size_t)参数
  • 字符标识:允许传入一个char参数。

根据 C++ 11 标准,只有下面这些签名是合法的:

char const*
unsigned long long
long double
char const, std::size_t
wchar_t const*, std::size_t
char16_t const*, std::size_t
char32_t const*, std::size_t

上面列出的第一个签名不要同字符串相混淆,应该被称为原始字面量 raw literal 操作符。例如:

char const* operator"" _r(char const* s)
{
    return s;
}

int main()
{
    std::cout << 12_r << '\n';
}

注意,你为字符串标识定义的标识操作符不能只带有一个const char*参数(而没有大小)。例如:

//警告,这个标识操作符并不能像预想的那样子工作
string operator"" S(const char* p);  
"one two"S;    //错误,没有适用的标识操作符

根本原因是如果我们想有一个“不同的字符串”,我们同时也想知道字符的个数。后缀可能比较短(例如,s是字符串的后缀,i是虚数的后缀,m是米的后缀,x是扩展类型的后缀),所以不同的用法很容易产生冲突,我们可以使用namespace(命名空间)来避免这些名字冲突:

namespace Numerics {
    // …
    class Bignum { /* … */ };
    namespace literals {
        operator"" X(char const*);
    }
}
using namespace Numerics::literals;

参考资料

C++11 用户自定义字面值
C++11 新特性:用户定义字面量
【c++11FAQ】用户定义数据标识
cpp11新特性详解与应用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,682评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,277评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,083评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,763评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,785评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,624评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,358评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,261评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,722评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,900评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,030评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,737评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,360评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,941评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,057评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,237评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,976评论 2 355

推荐阅读更多精彩内容

  • 本文转自:http://www.cnblogs.com/lidabo/p/5225868.html 1)字符串操作...
    XiaohuiLI阅读 9,519评论 0 0
  • 一、字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 s...
    JaiUnChat阅读 1,659评论 0 7
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,983评论 6 13
  • 今日,我却躺着病床上眼睛艰难的睁着,想顺着心思写点什么,我从未担心过眼睛会患疾病,我一直认为眼睛是我脸部器官里最...
    六月的雪355阅读 376评论 5 2
  • 你从未爱过我 想到这一点便使我心生怒火 我苦苦爱了你三十年! 如果不是那天你 故作认真地说你爱我 我又怎么会傻子一...
    日思夜幻阅读 255评论 0 0