C++ 库命名空间与 C linux 函数之间的名称冲突
Name collision between c++ library namespace and C linux function
Linux <ncurses.h>
头文件定义函数 meta
, and the C++ metaprogramming library meta
将其所有代码放在全局命名空间 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>
编译但可能无法 link 因为 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>
的内容未声明 [=11=],那么您将 运行 陷入您引用的问题:库是使用全局命名空间中的函数构建的,但是客户端代码正在查看 linux
命名空间中代码的定义。由于命名空间会影响损坏的名称(这就是它防止冲突的方式),您的代码将无法 link。所有 linux::*
函数都将显示为未解析的外部对象。
要使此工作正常,您需要确保 none 的库代码已声明 extern "C"
,并在 中指定命名空间 header(和库源文件),re-compile 具有这些声明的库,因此库及其客户端代码就该代码所在的命名空间达成一致。
Linux <ncurses.h>
头文件定义函数 meta
, and the C++ metaprogramming library meta
将其所有代码放在全局命名空间 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>
编译但可能无法 link 因为
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>
的内容未声明 [=11=],那么您将 运行 陷入您引用的问题:库是使用全局命名空间中的函数构建的,但是客户端代码正在查看 linux
命名空间中代码的定义。由于命名空间会影响损坏的名称(这就是它防止冲突的方式),您的代码将无法 link。所有 linux::*
函数都将显示为未解析的外部对象。
要使此工作正常,您需要确保 none 的库代码已声明 extern "C"
,并在 中指定命名空间 header(和库源文件),re-compile 具有这些声明的库,因此库及其客户端代码就该代码所在的命名空间达成一致。