字面量常量运算符,switch case 字符串的简单举例,constexpr使用详解

编程世界无奇不有,很多人肯定在C++代码中看到过如下所示的东西:

double area = 80_rr;

或者有类似这种的

String str = arg;

Switch(str.c_str())

{

Case:...

}

等类似的东西,what C++ switch还可以直接对字符串进行判断?我越来越好奇了,这些东西如何来的?下面就来解开C++的神奇面纱,C++ 11特性向上兼容 ---用户定义字面量运算符

规范自带的float m = 4.0f; 后面的f是字面量运算符,现在实现如规范一样的东西,请继续往下看。

 

用户定义字面量运算符

用户定义字面量所调用的函数被称为字面量运算符(或若它是模板,则被称为字面量运算符模板)。

C++ 11的形式为

Operator “”  name

C++14的形式为

Operator “”name

这里特别指出:

用户自定义字面量运算符的参数(返回值随意),函数的参数必须是以下的类型

1、const char *

2、unsigned long long int

3、long double

4、char

5、wchar_t

6、char16_t

7、char32_t

8、const char * , std::size_t

9、const wchar_t * , std::size_t

10、 const char16_t * , std::size_t

11、const char32_t * , std::size_t

后四个多了一个size_t的参数:其中字符串是无ud-suffix 的字面量,且size_t 则是其排除空终止字符的长度(这里官方的解释,搞那么深奥,说简单点就是你传入的字符串的长度,比如你的字符串是”hello”,那么后面的size就等价于strlen(“hell”),好理解多了吧)

 

注意:

constexpr size_t operator"" _hash2(char const*p)

{

return strlen(p);

}

constexpr size_t operator "" _hash1(char const*p, size_t  len)

{

return len;

}

 

 

  很多人会有疑问,为何有了上面的1的参数格式,还要多一个8这种两个参数的格式呢?

这里就解释一下吧,前者适用于123_hash2 这种格式的字面量,后者适用于”123”_hash1 这种格式,是不是看出不同了呢?如果有其他使用格式,希望回复我哦,我会去一一给大家一个使用的测试的。

 

C++14简单的看起来就是C++11“”后面必须带空格,C++14里面就可以省去空格写在一起。

下面简单的举一个例子:

constexpr long double operator"" _v( long double deg )

{

    return deg*3.141592;

}

那么你在函数调用时,可以定义:

double are = 1.0_v;

输出are的值即为:3.141592

看了这个例子基本知道用户自定义字面量运算符的作用了,即在程序编译的时候,将1.0_v通过上面定义的函数得出一个右值,然后赋值给are。即你可以将1.0_v也看成一个常量值。

但是请注意,C++11 C++14等用户自定义的字面量运算符必须以_(下划线开头)如上面的_v,或许是为了避免和标准头文件里面的 不带下划线的字面量常量发生冲突,不然我真想不出C++14里面都有operator""if   operator""i   operator""il 这种形式的字面量常量定义,为何用户不能必须使用_下划线了。

 

 

如果你看到这里了,那么就很好理解了,为何switch可以对字符串进行case比较了,因为case后面的值不能是字符串,但是有了用户自定义字面量运算符,那么用户自己完全可以将字符串转换成整形数据即可了。比如下面这个例子:

很多人想在C++中实现如下功能的switch

const char* str = "first";  

switch(str){  

case "first":  

    cout << "1st" << endl;  

    break;  

case "second":  

    cout << "2nd" << endl;  

    break;  

case "third":  

    cout << "3rd" << endl;  

    break;   

}  

但是直接写肯定是编译不过的,那么现在利用C++11中的用户自定义字面量运算符来实现上面想要实现的switch功能吧:

 

//这里是定义一个hash序列,

using namespace std;

typedef std::uint64_t hash_t;

 

constexpr hash_t prime = 0x100000001B3ull;

constexpr hash_t basis = 0xCBF29CE484222325ull;

hash_t hash_(char const*str)  //功能和hash_compile_time功能相同,处理阶段不同,一个是运行时没,一个是编译时

{

hash_t ret{ basis };

 

while (*str) {

ret ^= *str;

ret *= prime;

str++;

}

 

return ret;

}

//下面定义的预处理函数,使得和上面的hash_值得到的结果一样,因为字串需要调用hash_函数将字串转化成hash序列,hash_compile_time函数在预编译时也能达到相同值,所以两个函数是一一对应的

constexpr hash_t hash_compile_time(char const*str, hash_t last_value = basis)

{

return *str ? hash_compile_time(str + 1, (*str ^last_value) * prime) : last_value;

}

//这里是为了定义一个用户字面量运算符_hash

constexpr unsigned long long operator "" _hash(char const*p, size_t)

{

return hash_compile_time(p);

}

 

void simple_switch(char const*str)

{

using namespace std;

switch (hash_(str)) {

case "first"_hash:

cout << "1st" << endl;

break;

case "second"_hash:

cout << "2nd" << endl;

break;

case "third"_hash:

cout << "3rd" << endl;

break;

}

}

 

int main()

{

 

simple_switch("first");

system("pause");

}

输出结果即为 1st,上面switch部分代码截取自http://blog.csdn.net/yozidream/article/details/22789147的博客。

怎么样,各位小伙伴,是不是看了用户字面量运算符后,感觉是不是很舒服,很多程序可以将处理定义在编译阶段,能够提高程序运行时的效率,但是上面的switch显然有大量的hash运算,并不是最优的解决方案,因为你完全可以用map表直接取值就好了,使用只是为了给大家更为贴切的讲述这个原理噶。

可能大家对于模板特化时求累积等编译时得出系统允许的栈长度,但是这和用户字面量运算符有一定的差异。需要了解更多请关注  丁丁猫编程 D-CAT  里面会有大量技术性文章分阶段分享给大家。

 

丁丁猫编程 D-CAT   丁丁猫编程 D-CAT   丁丁猫编程 D-CAT   微信的哦

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值