简体   繁体   English

为什么文字运算符不能正常模板化?

[英]Why can't the literal operator be templated normally?

I'm currently working on a compile time expression tree and wanted to use a literal operator to create an expression from a literal.我目前正在研究编译时表达式树,并希望使用文字运算符从文字创建表达式。 Since all literals are allowed as an expression I wanted to template the literal operator like:由于所有文字都被允许作为表达式,我想将文字运算符模板化,例如:

template <typename T>
constexpr auto operator""_ve(T value)
{
    return value_expression(value);
}

This didn't compile so I did some research and found out that the only allowed template is这没有编译,所以我做了一些研究,发现唯一允许的模板是

template <char...> XYZ operator "" _abc();

Why is that?这是为什么? Do I really have to specify each overload manually?我真的必须手动指定每个重载吗?

Do I really have to specify each overload manually?我真的必须手动指定每个重载吗?

Yes.是的。

Literal operators are not called via overload resolution (not really).文字运算符不是通过重载解析调用的(不是真的)。 Overload resolution can do things like allow for implicit conversions or other unpleasant things.重载解析可以做一些事情,比如允许隐式转换或其他不愉快的事情。 Because literal operators are (typically) invoked by the compiler on compile-time-generated values, it's a good idea to make sure that the writer of a literal operator gets the entire literal value (as best as the compiler can provide, of course), not a converted value.因为文字运算符(通常)由编译器在编译时生成的值上调用,所以最好确保文字运算符的作者获得整个文字值(当然,编译器可以提供的最好) , 不是转换后的值。

This is actually quite important.这实际上非常重要。 Consider the case where you want to write a literal that takes integer values but not floating-point values.考虑这样一种情况:您想编写一个采用整数值而不是浮点值的文字。 That is, 12.3_lit should be a compile error.也就是说, 12.3_lit应该是编译错误。 Your signature for your operator would take unsigned long long , but a long double is implicitly convertible to an unsigned long long .您的运算符签名将采用unsigned long long ,但long double可隐式转换为unsigned long long Therefore, 12.3_lit would be valid when you don't want it to be.因此, 12.3_lit在您不希望它是有效的时候是有效的。

Now in theory you could avoid such scenarios by = delete ing floating-point signatures explicitly.现在理论上你可以通过= delete显式地= delete浮点签名来避免这种情况。 But... UDLs were invented at a time when = delete wasn't really a thing, so that wasn't necessarily an option.但是...... UDL 是在= delete并不是真正的东西的时候发明的,所以这不一定是一种选择。

To avoid these scenarios, the literal operator dispatch logic explicitly looks for a particular set of signatures (based on the kind of literal being processed).为了避免这些情况,文字运算符分派逻辑显式查找一组特定的签名(基于正在处理的文字类型)。 If you don't have a long double overload for the operator (or a raw literal version), then upon encountering 12.3_lit , the system will find no appropriate function and generate a compile error.如果操作符没有long double重载(或原始文字版本),那么在遇到12.3_lit ,系统将找不到合适的函数并生成编译错误。

Because the system searches for specific signatures rather than using overload resolution, literal operator signatures (including templates) are restricted to being exactly and only the signatures that the literal operator dispatch logic will search for .因为系统搜索特定的签名而不是使用重载解析,所以文字运算符签名(包括模板)被限制为精确且仅是文字运算符分派逻辑将搜索的签名 No more, no less.不多也不少。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM