引用保留名称绝对是非法的吗?

Lig*_*ica 28 c++ language-lawyer c++11 c++14

std-proposal列表中,给出了以下代码:

#include <vector>
#include <algorithm>

void foo(const std::vector<int> &v) {
#ifndef _ALGORITHM
  std::for_each(v.begin(), v.end(), [](int i){std::cout << i; }
#endif
}
Run Code Online (Sandbox Code Playgroud)

为了这个问题的目的,让我们忽略为什么给出代码以及为什么它是这样编写的(因为有一个很好的理由,但这里没有关系).它假设这_ALGORITHM是标准头文件中的标头保护<algorithm>,随着一些已知的标准库实现一起提供.这里没有可移植性的固有意图.

现在,_ALGORITHM当然是一个保留名称,每个:

[C++11: 2.11/3]:此外,一些标识符保留供C++实现和标准库(17.6.4.3.2)使用,否则不得使用; 无需诊断.

[C++11: 17.6.4.3.2/1]: 某些名称和函数签名集始终保留给实现:

  • 每个包含双下划线_ _或以下划线开头后跟大写字母(2.12)的名称保留给实现以供任何使用.
  • 以下划线开头的每个名称都保留给实现,以用作全局名称空间中的名称.

我总是认为这段经文的目的是阻止程序员定义/改变/取消定义属于上述标准的名称,以便标准库实现者可以使用这些名称,而不必担心与客户端代码冲突.

但是,在std-proposal列表中,有人声称这段代码本身就是不正确的,只是引用了这样一个保留名称.我现在可以看到如何使用"不得以其他方式使用"这一短语[C++11: 2.11/3]:的确如此.

例如,给出的一个实际原理是宏_ALGORITHM可以扩展到一些擦除硬盘驱动器的代码.但是,考虑到规则的可能意图,我会说这种可能性更多地与名称的明显实现定义的*性质有关_ALGORITHM,而与它的引用完全是非法的关系不大.

*在英语语言意义上的"实现定义",而不是C++标准意义上的短语

我要说的是,只要我们很高兴我们将有实现定义的结果,并且我们应该调查宏对我们的实现意味着什么(如果它存在的话!),它本身不应该是非法的如果我们不试图修改它,请参考这样的宏.

例如,在整个地方使用以下代码来区分编译为C的代码和编译为C++的代码:

#ifdef __cplusplus
extern "C" {
#endif
Run Code Online (Sandbox Code Playgroud)

我从未听过有关此事的投诉.

所以你怎么看?"不得另行使用"包括简单地写这样的名字吗?或者它可能不是那么严格(可能指向调整标准措辞的机会)?

Ben*_*igt 18

它是否合法是特定于实现(和特定于标识符).

当标准赋予实现使用这些名称的唯一权利时,包括在用户代码中提供名称的权利.如果实现这样做,那很好.

但是,如果某个实现没有明确赋予您正确的权利,那么标准中没有明确表示"不得使用",并且您有未定义的行为.


Dan*_*rey 17

重要的部分是"保留给实施".这意味着编译器供应商可以使用这些名称甚至记录它们.然后,您的代码可以使用这些名称.这通常用于扩展,例如__builtin_expect,编译器供应商通过使用这些保留名称避免与您的标识符(由您的代码声明)发生冲突.甚至标准也会使用它们__attribute__来确保在添加新功能时不会破坏现有(合法)代码.

  • @LightningRacisinObrit好吧,**否则**.我理解该标准本身并不合法或非法,它保留了实施的权利.然后您的编译器供应商做出决定,默认为"不,不要使用它".但*否则*,如果他们记录这些标识符,它确实合法. (4认同)