为什么我的日志在 std 命名空间中?

2022-01-14 00:00:00 namespaces overloading c++

在下面的代码中,我定义了一个简单的 log 函数.在 main 我尝试 not 来调用它;我调用 std::log.然而,我自己的 log 被调用了;我看到日志!"在屏幕上.有谁知道为什么?我使用 G++ 4.7 和 clang++ 3.2.

In the code below, I define a trivial log function. In main I try not to call it; I call std::log. Nevertheless, my own log is called; and I see "log!" on screen. Does anyone know why? I use G++ 4.7 and clang++ 3.2.

#include <iostream>
#include <cmath>

double log(const double x) { std::cout << "log!
"; return x; }

int main(int argc, char *argv[])
{
  std::log(3.14);
  return 0;
}

推荐答案

C++ Standard 17.6.1.2 第 4 段(强调我的):

C++ Standard 17.6.1.2 paragraph 4 (emphasis mine):

除了第 18 到 30 条和附录 D 中的说明外,每个头 cname 的内容应与相应头 name.h 的内容相同,如在 C 标准库 (1.2) 或 C Unicode TR 中指定,视情况而定,就像通过包含一样.然而,在 C++ 标准库中,声明(在 C 中定义为宏的名称除外)在命名空间 std 的命名空间范围 (3.3.6) 内.未指定这些名称是否首先在全局命名空间范围内声明,然后通过显式 using-declarations (7.3.3) 注入命名空间 std.

Except as noted in Clauses 18 through 30 and Annex D, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in the C Standard library (1.2) or the C Unicode TR, as appropriate, as if by inclusion. In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).

g++ 采用后一种方式,因此一些相同的头文件可以在 C 和 C++ 中重复使用.所以允许g++在全局命名空间中声明和定义double log(double).

g++ does it the latter way so that some of the same header files can be reused for C and C++. So g++ is allowed to declare and define double log(double) in the global namespace.

第 17.6.4.3.3 节第 3 和第 4 段:

Section 17.6.4.3.3 paragraphs 3 and 4:

使用外部链接声明的标准 C 库中的每个名称都保留给实现用作具有 extern "C" 链接的名称,在命名空间 std 和在全局命名空间中.

Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.

使用外部链接声明的标准 C 库中的每个函数签名都保留给实现,以用作 extern "C"extern "C++"链接,或作为全局命名空间中命名空间范围的名称.

Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++"linkage, or as a name of namespace scope in the global namespace.

在第 17.6.4.3 节第 2 段的顶部:

And up at the top of Section 17.6.4.3 paragraph 2:

如果程序在保留名称的上下文中声明或定义名称,除非本条款明确允许,否则其行为未定义.

If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by this Clause, its behavior is undefined.

另一方面,您不得以任何方式声明或定义 ::log.

You, on the other hand, may not declare or define ::log in any way.

可惜的是,g++ 工具链没有给你任何错误信息.

It's too bad the g++ toolchain doesn't give you any error messages, though.

相关文章