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

时间:2013-10-25 10:32:00

标签: c++ g++ clang++

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

例如,以下代码:

#include <cstdlib>
float random() { return 0.0f; }
int main() { return 0; }

无法在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()’

> 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;

导致stdlib.h“污染”具有自己的random函数的全局命名空间。

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

5 个答案:

答案 0 :(得分:10)

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

  2. 标准写道:

      

    每个C头(每个头都有一个name.h形式的名称,就好像每个由相应的cname标头放置在标准库名称空间中的名称放在全局名称空间范围内。 未指定是否首先在名称空间std的名称空间范围(3.3.6)中声明或定义这些名称,然后通过显式使用声明将其注入全局名称空间范围(7.3 0.3)。

    这意味着,允许编译器 将这些符号同时放入全局范围和std命名空间

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

    但是,在std时仍然需要使用#include <cstdlib>命名空间,而在std时不要使用#include <stdlib.h>,以确保您的代码可以为所有编译器编译的实施方式。

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

答案 1 :(得分:6)

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

namespace MyFunc
{
float random() { return 0.0f; }
};

答案 2 :(得分:3)

一般情况下,您应该尽量避免重新声明。 您可以通过使用命名空间或将源拆分为包含cstdlib的文件和其他可以使用(名称冲突)函数的static版本的文件来完成此操作。

如果这不是一个选项,那么继续阅读。但请注意,以下内容可能非常特定于平台。

通过在我的位置查看我的cstdlibstdlib.h,我注意到有cstdlib决定是否包含stdlib.h或只是在abort命名空间中声明atextexitstd

显然你拉入了stdlib.h分支。进一步查看此文件,我注意到宏__BEGIN_NAMESPACE_STD以及稍后的__END_NAMESPACE_STD。也许你可以使用它,但它(顾名思义)是一些实现内部宏,不应该由你直接设置。但是,它应该出于某种原因,所以你可能有幸找到它。

经过多次搜索后发现random是几个未包含在__BEGIN_NAMESPACE_STD中的函数(和声明)之一。因此,这不是问题的解决方案。 (我发现了另一个宏_GLIBCPP_USE_NAMESPACES,它似乎也在内部用于#define __BEGIN_NAMESPACE_STD namespace std {)。

总而言之:这不是可行的路径,您应该使用上述解决方法之一。

答案 3 :(得分:2)

标准明确允许<c???>标头将C标准函数的名称带到全局名称空间。

答案 4 :(得分:0)

通常我更希望保持您的功能名称与定义为标准的名称不同。 对于ex在这里,可以使用函数名称作为myRandom而不是随机,这样我可以通知那些将在稍后维护我的代码的人,使用的函数不是定义为标准的函数。