我目前正在编译时的表达式树上,想使用文字运算符从文字中创建表达式。由于所有文字都可以用作表达式,因此我想对文字运算符进行模板化,例如:
template <typename T>
constexpr auto operator""_ve(T value)
{
return value_expression(value);
}
这个没有编译,所以我做了一些研究,发现唯一允许的模板是
template <char...> XYZ operator "" _abc();
这是为什么?我真的必须手动指定每个重载吗?
最佳答案
Do I really have to specify each overload manually?
是。
字面量运算符不是通过重载解析调用的(不是真的)。重载解析可以完成诸如允许隐式转换或其他不愉快的事情。因为文字运算符(通常)是由编译器在编译时生成的值上调用的,所以最好确保文字运算符的编写者获得整个文字值(当然,这是编译器所能提供的最好的) ,而不是转换后的值。
这实际上很重要。考虑一下您要编写一个采用整数值而不是浮点值的文字的情况。也就是说,
12.3_lit
应该是编译错误。您对运算符(operator)的签名将采用unsigned long long
,但long double
可隐式转换为unsigned long long
。因此,当您不想使用12.3_lit
时,它就会有效。现在从理论上讲,您可以通过
= delete
显式地浮点签名来避免此类情况。但是... UDL是在= delete
并不是真正的东西时发明的,因此这不一定是一种选择。为了避免出现这些情况,文字运算符会调度逻辑explicitly looks for a particular set of signatures(基于要处理的文字种类)。如果运算符(operator)没有
long double
重载(或原始文字版本),则在遇到12.3_lit
时,系统将找不到合适的函数并生成编译错误。因为系统搜索特定的签名而不是使用重载解析,所以文字运算符(包括模板)为restricted to being exactly and only the signatures that the literal operator dispatch logic will search for。不多不少。
关于c++ - 为什么文字操作符不能正常地模板化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60196812/