是每个“正常"的吗?使用用户定义的文字未定义的行为? [英] Is every "normal" use of user-defined literals undefined behavior?

查看:61
本文介绍了是每个“正常"的吗?使用用户定义的文字未定义的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用户定义的文字必须以下划线开头.

User defined literals must start with an underscore.

这是一个或多或少众所周知的规则,您可以在每个谈论用户文字的外行词站点上找到.自从胡说八道"以来,我(甚至可能是其他人)就一直公然无视这条规则.当然,现在这绝对是不正确的.从最严格的意义上讲,它使用了保留的标识符,从而调用了Undefined Behavior(尽管实际上从编译器中获得的耸耸肩不多.)

This is a more or less universally well-known rule that you can find on every layman-worded site talking about user literals. It is also a rule which I (and possibly others?) have been blatantly ignoring ever since on a "what a bullshit" base. Now of course, that's strictly not correct. In the strictest sense, this uses a reserved identifier, and thus invokes Undefined Behavior (although you don't get as much as a shrug from the compiler, practically).

因此,考虑是否应该继续故意忽略标准的那部分(我认为无用),我决定查看实际编写的内容.因为,每个人都知道有什么关系.重要的是标准中写的是什么.

So, pondering whether I should continue to deliberately ignore that (in my opinion useless) part of the standard or not, I decided to look at what's actually written. Because, you know, what does it matter what everybody knows. What matters is what's written in the standard.

[over.literal] 声明保留了一些"文字后缀标识符,并链接到 [usrlit.suffix] .后者指出全部保留,但下划线开头的保留.好的,这几乎就是我们已经知道的,明确编写的(或者相反编写的).

[over.literal] states that "some" literal suffix identifiers are reserved, linking to [usrlit.suffix]. The latter states that all are reserved, except those that start with an underscore. OK, so that's pretty much exactly what we already knew, explicitly written (or rather, written backwards).

此外, [over.literal] 包含一个 Note ,它暗示了一个显而易见但令人困扰的事情:

Also, [over.literal] contains a Note which hints to an obvious but troubling thing:

除上述约束外,它们是普通的命名空间范围函数和函数模板

except for the constraints described above, they are ordinary namespace-scope functions and function templates

好吧,确定是.它无处表明它们不是,所以您还希望它们成为什么.

Well, sure they are. Nowhere does it say that they aren't, so what else would you expect them to be.

但是请稍等. [lex.name] 明确指出,保留每个在全局命名空间中以下划线开头的标识符.

But wait a moment. [lex.name] explicitly states that each identifier that begins with an underscore in the global namespace is reserved.

现在,通常是文字运算符,除非您将其显式地放入全局命名空间中的命名空间中(我相信没有人这样做!?).因此,该名称(必须以下划线开头)必须保留.没有提及特殊例外.因此,每个名称(带下划线或不带下划线)都是保留名称.

Now, a literal operator usually, unless you explicitly put it into a namespace (which, I believe nobody does!?) is very much in the global namespace. So, the name, which must begin with an underscore, is reserved. There is no mention of a special exception. So, every name (with underscore, or without) is a reserved name.

您是否确实确实希望将用户定义的文字放入命名空间中,因为正常"用法(是否带有下划线)使用的是保留名称?

Are you indeed expected to put user defined literals into a namespace because the "normal" usage (underscore or not) is using a reserved name?

推荐答案

是:禁止使用 _ 作为全局标识符的开始以及要求启动非标准UDL的组合 _ 表示您不能将它们放在全局名称空间中.但是您不应该使用尤其是 UDL来破坏全局命名空间,所以这不是什么大问题.

Yes: the combination of forbidding the use of _ as the start of a global identifier coupled with requiring non-standard UDLs to start with _ means that you can't put them in the global namespace. But you shouldn't be dirtying up the global namespace with stuff, especially UDLs, so that shouldn't be much of a problem.

标准使用的传统习惯用法是将UDL放在 literals 命名空间中(如果您有不同的UDL组,则将它们放在不同的 inline命名空间中在该名称空间下).该 literal 命名空间通常位于您的主要命名空间之下.当您要使用一组特定的UDL时,请使用名称空间my_namespace :: literals 或包含您选择的字面量的子命名空间调用.

The traditional idiom, as used by the standard, is to put UDLs in a literals namespace (and if you have different sets of UDLs, then you put them in different inline namespaces below that namespace). That literals namespace is typically underneath your main one. When you want to use a particular set of UDLs, you invoke using namespace my_namespace::literals or whichever sub-namespace contains your literal set of choice.

这很重要,因为UDL往往大量缩写.例如,该标准将 s 用于 std :: string ,但也用于 std :: chrono :: duration 秒.尽管它们确实适用于不同种类的文字(应用于字符串的 s 是字符串,而应用于数字的 s 是持续时间),但有时可能会造成混淆读取使用缩写文字的代码.因此,您不应该对库的所有用户都使用文字.他们应该选择使用它们.

This is important because UDLs tend to be heavily abbreviated. The standard for example uses s for std::string, but also for std::chrono::duration of seconds. While they do apply to different kinds of literals (s applied to a string is a string, while s applied to a number is a duration), it can sometimes be confusing to read code that uses abbreviated literals. So you shouldn't throw literals at all users of your library; they should opt-in to using them.

通过使用不同的名称空间( std :: literals :: string_literals std :: literals :: chrono_literals ),用户可以预先了解哪个名称空间他们想要在代码的哪个部分中使用的一组文字.

By using different namespaces for these (std::literals::string_literals and std::literals::chrono_literals), the user can be up-front about which sets of literals they want in which parts of code.

这篇关于是每个“正常"的吗?使用用户定义的文字未定义的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆