扩展 std 命名空间被认为是未定义行为的原因是什么?
What are the reasons that extending the std namespace is considered undefined behavior?
为什么向 std
命名空间添加名称是未定义的行为?
显而易见的答案是 "because the standard says so," 例如在 C++14 中 [namespace.std] 17.6.4.2.1/1:
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std
or to a
namespace within namespace std
unless otherwise specified. ...
但是,我真的很想知道这个裁决的原因。我当然可以理解,添加 std
中已有的名称重载可能会破坏行为;但为什么添加新的、不相关的名称会成为问题?
程序已经可以在 std
内部使用宏造成严重破坏,这就是为什么几乎所有标准库实现都必须仅由保留名称组成(双下划线和起始下划线后跟大写字母)对于所有非public部分。
我真的很想知道这样的情况可能会出现问题:
namespace std
{
int foo(int i)
{ return i * 42; }
}
#include <algorithm> // or one or more other standard library headers
当这是完全合法且标准库必须应对时:
#define foo %%
#include <algorithm> // or one or more other standard library headers
此未定义行为的基本原理是什么?
这里有几个原因:
- 即使 headers 中的名称必须被丑化以避免与宏交互,但实际实现代码的源文件中的名称不存在此要求。如果一个实现确实使用
::std::foo(int)
作为其实现的一部分,那将违反单一定义规则。
- 该标准有望增长。如果可以将名称添加到命名空间
std
,则添加到标准 C++ 库的任何名称都可能是重大更改。在某种程度上,这已经是正确的,因为任何这样的名称都可以是一个宏,但打破这些名称被认为是可以接受的。
- 实际上不需要将名称添加到命名空间
std
:它们可以添加到任意其他命名空间,即,即使上面给出的动机不是特别强烈,也不考虑限制任何形式的物质。 ...并且如果 是 向命名空间 std
添加名称的原因,它显然 确实 影响行为。
为什么向 std
命名空间添加名称是未定义的行为?
显而易见的答案是 "because the standard says so," 例如在 C++14 中 [namespace.std] 17.6.4.2.1/1:
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace
std
or to a namespace within namespacestd
unless otherwise specified. ...
但是,我真的很想知道这个裁决的原因。我当然可以理解,添加 std
中已有的名称重载可能会破坏行为;但为什么添加新的、不相关的名称会成为问题?
程序已经可以在 std
内部使用宏造成严重破坏,这就是为什么几乎所有标准库实现都必须仅由保留名称组成(双下划线和起始下划线后跟大写字母)对于所有非public部分。
我真的很想知道这样的情况可能会出现问题:
namespace std
{
int foo(int i)
{ return i * 42; }
}
#include <algorithm> // or one or more other standard library headers
当这是完全合法且标准库必须应对时:
#define foo %%
#include <algorithm> // or one or more other standard library headers
此未定义行为的基本原理是什么?
这里有几个原因:
- 即使 headers 中的名称必须被丑化以避免与宏交互,但实际实现代码的源文件中的名称不存在此要求。如果一个实现确实使用
::std::foo(int)
作为其实现的一部分,那将违反单一定义规则。 - 该标准有望增长。如果可以将名称添加到命名空间
std
,则添加到标准 C++ 库的任何名称都可能是重大更改。在某种程度上,这已经是正确的,因为任何这样的名称都可以是一个宏,但打破这些名称被认为是可以接受的。 - 实际上不需要将名称添加到命名空间
std
:它们可以添加到任意其他命名空间,即,即使上面给出的动机不是特别强烈,也不考虑限制任何形式的物质。 ...并且如果 是 向命名空间std
添加名称的原因,它显然 确实 影响行为。