Linux <ncurses.h>头文件定义了meta函数,C ++元编程库meta将其所有代码放在全局名称空间中。
我如何在同一个C ++程序中使用这两个程序(不一定是相同的TU,但那样会很好)? 有没有办法解决名称冲突?
我可以想到两个脆弱的解决方法,但它们很容易中断:
解决方法A:
namespace linux { #include <ncurses.h> } // namespace linux using linux::max_align_t; // ncurses assumes it is in the global namespace #include <meta/meta.hpp>
编译但可能无法链接,因为ncurses符号预计在全局名称空间中。
解决方法B:
#include <ncurses.h> namespace cpp { #include <meta/meta.hpp> } // namespace cpp
是非常脆弱的,因为只要meta库不假定它的任何符号都在全局名称空间中,它就会工作。 也就是说,如果库需要在内部消除一个符号的歧义,并使用::meta::symbol_name ,那么这种方法将会中断。
我会建议解决方法C:隔离你的代码,使meta库的使用和ncurses使用在你的项目中的单独的翻译单位。 这种方式在任何特定的翻译单元中都没有一个符号被用作名称空间和全局函数。
我相当肯定,A和B都不会真正起作用,至少是如此。 你已经指出了其中的一个,但我认为这是两个可能性较小。 有两个基本上是彼此镜像的问题。
如果将ncurses的代码声明为extern "C" (对于许多已经用于C ++的C库而言是典型的),那么用名称空间包围它们实际上并不起作用 – extern "C"声明基本上忽略了命名空间在全局命名空间中声明一个函数。 命名空间不会改变任何东西,你仍然会碰撞。
如果<ncurses.h>的内容没有声明为extern "C" ,那么你会遇到你引用的问题:库是用全局命名空间中的函数构建的,但客户端代码在linux命名空间。 由于命名空间会影响重名的名称(这就是它如何防止碰撞),所以您的代码将无法链接。 所有的linux::*函数都会显示为无法解析的外部数据。
为了使这个工作,你需要确保没有任何库代码被声明为extern "C" ,并指定头(和库源文件) 内的名称空间,并用这些声明重新编译库,所以库并且它的客户端代码同意代码所在的命名空间。