扩展std命名空间被认为是未定义的行为的原因是什么?

Rei*_*ica 18 c++ undefined-behavior c++-standard-library

为什么在std名称空间未定义的行为中添加名称?

显而易见的答案是"因为标准这样说",例如在C++ 14 [namespace.std] 17.6.4.2.1/1中:

如果C++程序将声明或定义添加到命名空间std或命名空间中的命名空间std,则除非另有说明,否则C++程序的行为是未定义的....

但是,我真的对这项裁决的原因感兴趣.我当然可以理解添加已经存在的名称的重载std可能会破坏行为; 但为什么添加新的,无关的名称是一个问题?

程序已经可以在std宏内部造成严重破坏,这就是为什么几乎所有标准库实现都必须由所有非公共部分的保留名称(双下划线和起始下划线后跟资本)组成.

我真的会对这样的情况感兴趣:

namespace std
{
  int foo(int i)
  { return i * 42; }
}

#include <algorithm>  // or one or more other standard library headers
Run Code Online (Sandbox Code Playgroud)

当这是完全合法的,标准库必须应对:

#define foo %%

#include <algorithm>  // or one or more other standard library headers
Run Code Online (Sandbox Code Playgroud)

这种未定义行为的基本原理是什么?

Die*_*ühl 8

原因如下:

  1. 即使标题中的名称必须被允许以避免与宏的交互,实际执行代码的源文件中的名称也不存在此要求.如果某个实现确实::std::foo(int)用作其实现的一部分,那么它将违反一个定义规则.
  2. 该标准有望增长.如果名称可以添加到命名空间std,那么添加到标准C++库的任何名称都可能会发生重大变化.在某种程度上,这已经是正确的,因为任何这样的名称都可以是一个宏,但是打破它们被认为是可以接受的.
  3. 实际上不需要将命名空间添加到命名空间std:它们可以添加到任意其他命名空间,即,即使上面给出的动机不是特别强,也不认为限制是任何形式的问题.......如果有有理由名称添加到命名空间std它显然不会影响行为.