是否可以在命名空间中放置标准的纯C头#include指令?

mic*_*c_e 13 c++ namespaces include

可能重复:
在命名空间块中包装#include是个好主意吗?

log在全局命名空间(::log)中有一个带有类的项目.

因此,自然地,之后#include <cmath>,编译器在每次尝试实例化我的日志类的对象时都会给出错误消息,因为<cmath>使用许多三字母方法污染全局命名空间,其中一个是对数函数log().

因此,有三种可能的解决方案,每种解决方案都有其独特的丑陋副作用.

  • 将日志类移动到它自己的命名空间,并始终使用它的完全限定名称访问它.我真的想避免这种情况,因为记录器应尽可能方便使用.
  • 编写一个mathwrapper.cpp文件,它是项目中唯一包含的文件<cmath>,并<cmath>通过包装器提供所有必需的功能namespace math.我不想使用这种方法,因为我必须为每个必需的数学函数编写一个包装器,它会增加额外的调用惩罚(部分由-flto编译器标志取消)
  • 我正在考虑的解决方案:

更换

#include <cmath>
Run Code Online (Sandbox Code Playgroud)

通过

namespace math {
#include "math.h"
}
Run Code Online (Sandbox Code Playgroud)

然后通过计算对数函数math::log().

我已经尝试过了,确实可以按预期编译,链接和运行.但它确实有多个缺点:

  • 它(显然)不可能使用<cmath>,因为<cmath>代码通过其完全限定的名称访问函数,并且不推荐在C++中使用它.
  • 我对它有一种非常非常糟糕的感觉,就好像我会受到猛禽的攻击和活着.

所以我的问题是:

  • 是否有任何建议/约定/等禁止在名称空间中包含指令?
  • 可能有什么问题

    • 不同的C标准库实现(我使用glibc),
    • 不同的编译器(我使用g ++ 4.7,-std = c ++ 11),
    • 链接?
  • 你有没有试过这样做?
  • 有没有其他方法可以从全局命名空间中消除数学函数?

我在stackoverflow上发现了几个类似的问题,但大多数是关于包含其他C++头文件,这显然是一个坏主意,而那些没有关于C库链接行为的矛盾陈述.另外,额外放入#include <math.h>内部extern "C" {}是否有益?

编辑

因此,我决定做其他人正在做的事情,并将我的所有代码放在项目命名空间中,并在包含时使用它的完全限定名称访问记录器<cmath>.

CB *_*ley 18

不,您正在考虑的解决方案是不允许的.实际上,这意味着您正在更改头文件的含义.您正在更改其所有声明以声明不同命名的函数.

这些更改的声明将与标准库函数的实际名称不匹配,因此,在链接时,任何标准库函数都不会解析对已更改声明声明的函数的调用,除非它们恰好已被声明extern "C"允许 - 但是不推荐 - 适用于来自C标准库的名称.

ISO/IEC 14882:2011 17.6.2.2/3 [using.headers]适用于C标准库头文件,因为它们是C++标准库的一部分:

翻译单位应仅在任何外部声明或定义[*]之外包括标题,并且应在该翻译单元中第一次引用之前的词汇表中包括该标题,以及该标题中声明的任何实体.

[*]包括命名空间定义.


par*_*eek 6

为什么不将日志类放在它自己的命名空间中并使用typedef namespace::log logger;以更方便的方式避免名称冲突?