起因:
在阅读cpp-httplib源码时看到下边这段代码
inline constexpr unsigned int operator"" _t(const char *s, size_t l) {
return str2tag_core(s, l, 0);
}
以及他的运用
"css"_t
第一次见到这种写法,由于operator是运算符重载,猜测是重载某种类型的运算符,查到这种叫做“字面量运算符”,具体可以参考下边这篇文章
C++操作符重载总结、字面量运算符
在这里根据查到的资料做一下总结和example
概念:
- 定义形式 :形如
T operator"" name(T1, T2)
,其中name是用户自定义的后缀,例如unsigned int operator“” _t(const char*s, size_t l)
,用的话这样使用"123"_t
。一般建议后缀开头是下划线。 - 字面量重载运算符可以把字面值常量,(注意只能是字面值常量,也就是“123”,123,1.23,‘a’这样,不能是变量。),转化为需要的类型对象。
- 注意字面值常量不能是成员函数。
使用要点:根据字面值类型的不同,操作符函数可以接受的参数也是不一样的。
- 字面值是整数:操作符只能接受unsigned long long 或者 const char*作为参数。
- 字面量为浮点数,操作符函数只可接受 long double 或者 const char* 为参数。
- 字面量为字符串,操作符函数只可接受 const char*,size_t为参数。
- 字面量为字符,则操作符函数只接受一个 char 为参数。
例如:
- 整数
int operator"" _n(unsigned long long i){
return i / 10;
}
void test_n(){
int a = -21474836470_n;
cout << a << endl;
}
并不会出现溢出,并且和直接调用n还不一样,似乎不是把a转换成unsignde long long之后进行计算,也会考虑本身的符号。
可能是在计算的时候先不考虑符号,计算完再把符号填上去,毕竟这个是字面值运算符,完全可以放在编译期间运算。
- 浮点数
double operator"" _f(long double i){
return i / 10;
}
void test_f(){
double a = -214748.36470_f;
cout << a << endl;
}c
- 字符串
unsigned int operator"" _s(const char*s, size_t l){
cout << "s = " << s << endl << "l = " << l << endl;
return l;
}
void test_s(){
unsigned int a = "12346"_s;
cout << a << endl;
}
- 字符
int operator"" _c(char c){
return c;
}
void test_c(){
cout << 'a'_c << ", " << 'A'_c << endl;
}
用处:简化操作
#include <iostream>
#include <stdexcept>
#include <string>
struct YYYYMMDD
{
int yyyy;
int mm;
int dd;
};
YYYYMMDD operator "" _yyyymmdd( const char * ymd_str, std::size_t ymd_size)
{
if (ymd_size<8)
{
throw std::invalid_argument( "invalid ymd string:"+std::string(ymd_str));
}
YYYYMMDD ymd_struct;
ymd_struct.yyyy = (ymd_str[0]-'0')*1000+(ymd_str[1]-'0')*100+(ymd_str[2]-'0')*10+(ymd_str[3]-'0');
ymd_struct.mm = (ymd_str[4]-'0')*10+(ymd_str[5]-'0');
ymd_struct.dd = (ymd_str[6]-'0')*10+(ymd_str[7]-'0');
return ymd_struct;
}
YYYYMMDD operator "" _yyyymmdd(unsigned long long int ymd_num)
{
if(ymd_num<10000000 || ymd_num>30000000)
{
throw std::invalid_argument( "invalid ymd num:"+ymd_num);
}
YYYYMMDD ymd_struct;
ymd_struct.yyyy = ymd_num/10000;
ymd_struct.mm = (ymd_num%ymd_struct.yyyy)/100;
ymd_struct.dd = ymd_num%ymd_struct.yyyy%ymd_struct.mm;
return ymd_struct;
}
int main()
{
auto ymd_struct = 20001101_yyyymmdd;
std::cout<<"year:"<<ymd_struct.yyyy<<std::endl;
std::cout<<"month:"<<ymd_struct.mm<<std::endl;
std::cout<<"day:"<<ymd_struct.dd<<std::endl;
auto ymd_struct1 = "20001101"_yyyymmdd;
std::cout<<"year:"<<ymd_struct1.yyyy<<std::endl;
std::cout<<"month:"<<ymd_struct1.mm<<std::endl;
std::cout<<"day:"<<ymd_struct1.dd<<std::endl;
return 0;
}