用户定义的文字定义

时间:2017-01-21 21:56:00

标签: c++ c++11 user-defined-literals

我正在查看cppreference page for user defined文字,除了一些例子,我想我理解了所有内容

template <char...> double operator "" _π(); // OK

此操作符如何工作?你怎么称呼它?

double operator"" _Z(long double); // error: all names that begin with underscore
                                   // followed by uppercase letter are reserved
double operator""_Z(long double); // OK: even though _Z is reserved ""_Z is allowed

上述两个功能有什么区别?如果第一个函数不是错误,那么调用第一个函数而不是第二个函数会有什么不同?

谢谢!

2 个答案:

答案 0 :(得分:6)

template <char...> double operator "" _π(); // OK
     

此操作符如何工作?你怎么称呼它?

1.234_π会致电operator "" _π<'1', '.', '2', '3', '4'>()。此表单允许您检测通常无法检测到的拼写差异(例如1.21.20),并允许您避免由于1.2无法准确表示而导致的舍入问题甚至是long double

double operator"" _Z(long double); // error: all names that begin with underscore
                                   // followed by uppercase letter are reserved
double operator""_Z(long double); // OK: even though _Z is reserved ""_Z is allowed
     

上述两个功能有什么区别?

C ++标准根据令牌定义语法,您可以将其解释为单词。 "" _Z是两个令牌,""_Z""_Z是一个令牌。

这种区别很重要:给定#define S " world!",然后"Hello" S,空格是使S成为独立标记的原因,使其无法被视为用户定义的文字后缀。< / p>

为了便于编码,在定义这些函数时通常允许"" _Z""_Z语法,但"" _Z语法要求将_Z视为标识符。当实现将_Z预定义为宏或将其声明为自定义关键字时,这可能会导致问题。

答案 1 :(得分:1)

据我所知,两种签名之间没有区别。

问题是标准_Z在技术上是由标准保留的。主要区别在于有一个空间:

double operator""/*space*/_Z(long double); 

double operator""_Z(long double); 

删除空间基本上是一种解决方法,理论上可以抑制错误(或更可能是警告)。

至于你如何使用它们,你看过你列出的链接中的例子吗?

#include <iostream>

// used as conversion
constexpr long double operator"" _deg ( long double deg )
{
    return deg*3.141592/180;
}

// used with custom type
struct mytype
{
    mytype ( unsigned long long m):m(m){}
    unsigned long long m;
};
mytype operator"" _mytype ( unsigned long long n )
{
    return mytype(n);
}

// used for side-effects
void operator"" _print ( const char* str )
{
    std::cout << str;
}

int main(){
    double x = 90.0_deg;
    std::cout << std::fixed << x << '\n';
    mytype y = 123_mytype;
    std::cout << y.m << '\n';
    0x123ABC_print;
}

用户定义文字背后的想法是允许创建一个运算符,该运算符可以应用于内置类型,可以将内置文字转换为另一种类型。

编辑:

要调用其中一个运算符,您只需将运算符作为后缀附加到值文字。所以给出:

// used as conversion
constexpr long double operator"" _deg ( long double deg )
{
    return deg*3.141592/180;
}

调用代码可以是例如:

long double d = 45_deg;

至于使用template <char...> double operator "" _π();或许请查看this.