防止std命名空间之外的标准函数

Cyg*_*sX1 16 c++ g++ clang++

我只使用特定于C++的头文件(例如<cstdlib>),但是我仍然获得全局声明的函数,而不仅仅是std命名空间中的函数.有没有办法,也许是编译器开关,以防止这种情况?

例如,以下代码:

#include <cstdlib>
float random() { return 0.0f; }
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)

无法在linux下编译,出现以下错误:

> g++ -c main.cpp main.o
main.cpp: In function ‘float random()’:
main.cpp:2:14: error: new declaration ‘float random()’
/usr/include/stdlib.h:327:17: error: ambiguates old declaration ‘long int random()’
Run Code Online (Sandbox Code Playgroud)

要么

> clang++ main.cpp -o main.o
main.cpp:2:7: error: functions that differ only in their return type cannot be overloaded
float random() { return 0.0f; }
/usr/include/stdlib.h:327:17: note: previous declaration is here
extern long int random (void) __THROW;
Run Code Online (Sandbox Code Playgroud)

导致stdlib.h使用自己的random函数"污染"全局命名空间.

请注意,在使用Visual Studio在Windows上进行编译时,我不会遇到这些问题.

yzn*_*pku 10

  1. <cstdlib>将始终填充std命名空间,有时定义全局符号,同时<stdlib.h>将始终定义全局符号,有时会填充std命名空间.这从实施到实施各不相同.

  2. 标准写道:

    每个C头(每个头都有一个表单的名称)的name.h行为就好像每个由相应cname头放在标准库命名空间中的名称放在全局命名空间范围内.未指定是否首先在命名空间的命名空间范围(3.3.6)中声明或定义这些名称std,然后通过显式using-declarations(7.3.3)将这些名称注入到全局命名空间范围中.

    这意味着,编译器允许把这些符号为全局范围和std命名空间的同时.

  3. 因此,我们认为优先选择一个头文件而不是另一个头文件没有优势.因为它们都很可能污染全球范围.

    但是,在确保您的代码可以为所有编译器实现进行编译std#include <cstdlib>,仍然需要使用命名空间.std#include <stdlib.h>

  4. 建议:不要在标准库中使用名称.首先,他们不能保证工作.(注意:很少有编译器实现实际上保持全局范围清洁#include <csomething>,所以永远不要依赖于此.)其次,它会使代码读取器和维护者感到困惑,因为几乎每个人都会认为标准名称实际上是标准名称,无论它们来自何处.

  • BTW,C++ 98不允许`<cxxx>`污染全局命名空间,C++引入了权限,因为许多实现很难满足要求(如果你不这样做很难或不可能)控制C库,我似乎记得libstdc ++人员描述这些困难的一篇论文,但我现在还没有找到它. (2认同)

Cae*_*sar 6

您可以在自己的命名空间中声明函数以防止声明冲突.

namespace MyFunc
{
float random() { return 0.0f; }
};
Run Code Online (Sandbox Code Playgroud)