9

Linux<ncurses.h>头文件定义函数meta,C++ 元编程库meta将其所有代码放在全局命名空间meta中。

我如何在同一个 C++ 程序中同时使用两者(不一定是同一个 TU,但这会很好)?有没有办法解决名称冲突?

我可以想到两个脆弱的解决方法,但它们很容易被打破:

  • 解决方法一:

     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用于该符号,则这种方法将失效。

4

2 回答 2

7

我建议解决方法 C:隔离您的代码,以便meta库的使用和ncurses使用位于项目中的单独翻译单元中。这样,在任何特定的翻译单元中,没有一个符号同时用作命名空间和全局函数。

于 2016-05-23T14:28:17.330 回答
1

我有理由确定 A 和 B 都不会真正起作用,至少按照给定的那样。您已经指向其中之一,但我认为这两者中的可能性较小。有两个问题基本上是互为镜像的。

如果其中的代码ncurses被声明为extern "C"(对于许多与 C++ 一起工作的 C 库来说是典型的),用命名空间包围它们实际上是行不通的——extern "C"声明基本上会忽略命名空间并在全局命名空间中声明一个函数。命名空间不会改变任何东西,你仍然会发生冲突。

如果<ncurses.h>未声明的内容extern "C",那么您将遇到您引用的问题:该库是使用全局命名空间中的函数构建的,但客户端代码正在查看命名空间中代码的定义linux 。由于命名空间会影响损坏的名称(这就是它防止冲突的方式),因此您的代码将无法链接。所有linux::*功能都将显示为未解决的外部。

为了使这项工作,您需要确保没有声明任何库代码,并extern "C"标头(和库源文件)中指定命名空间,并使用这些声明重新编译库,以便库及其客户端代码同意该代码所在的命名空间。

于 2016-05-23T15:26:20.727 回答