我该如何将BOOST封装在一个单独的命名空间中?

10
我希望在一个项目中同时编译两个版本的BOOST。最好能按以下方式使用它们:
boost_1_36_0::boost::shared_ptr<SomeClass> someClass = new SomeClass();
boost_1_35_0::boost::regex expression("[0-9]", boost_1_35_0::boost::regex_constants::basic);

我很好奇你为什么想要这样做。 - Ferruccio
这是为了在解决一些不兼容性问题时过渡到较新的库版本。没有任何永久性的改变。 - Eclipse
@Eclipse: 如果您的接口没有暴露任何 Boost 类型,则可以使用 ELF 可见性属性,隐藏除公共接口之外的所有内容。 - wilx
4个回答

11

我阅读(其实只是扫了一眼)了开发列表讨论。 没有简单的解决方案。 总结一下:

  1. 将头文件包装在命名空间声明中

namespace boost_1_36_0 {
    #include <boost_1_36_0/boost/regex.hpp>
}
namespace boost_1_35_0 {
    #include <boost_1_35_0/boost/shared_ptr.hpp>
}
  • 需要修改源文件
  • 由于宏不尊重命名空间,不允许两个版本同时包含在同一个翻译单元中。
  • 在包含头文件之前定义Boost

  • #define boost boost_1_36_0
        #include <boost_1_36_0/boost/regex.hpp>
    #undef boost
    #define boost boost_1_35_0
        #include <boost_1_35_0/boost/shared_ptr.hpp>
    #undef boost
    
    • 源文件可以简单地使用-Dboost=boost_1_36_0进行编译。
    • 仍然不能解决单个翻译单元中的宏冲突。
    • 由于这种情况确实会发生,因此某些内部头文件可能会出现混乱的包含关系。

    #if defined(SOME_CONDITION)
    #  define HEADER <boost/some/header.hpp>
    #else
    #  define HEADER <boost/some/other/header.hpp>
    #endif
    

    但是解决这些情况可能很容易。

  • 修改整个boost库,将namespace boost {..}替换为namespace boost_1_36_0 {...},然后提供一个命名空间别名。用BOOST_1_36_0_XYZ宏替换所有的BOOST_XYZ宏及其使用。
    • 如果你愿意付出努力,这可能会奏效。

  • 1
    如果你要修改头文件,你可以尝试类似于's/BOOST_/BOOST_1_36_0_/g'的方法来避免宏冲突。或许能行。 - Daniel James

    4

    使用bcp可以将boost库安装到特定位置,并将所有代码中的'namespace boost'替换为自定义别名。假设我们的别名是'boost_1_36_0',那么所有'namespace boost'代码块都将以'boost_1_36_0'开头。类似于

    bcp --namespace=boost_1_36_0 --namespace-alias shared_ptr regex /path/to/install
    

    但请您自行查看链接中的文档,因为我不确定它是否是合法的语法。


    1

    @Josh: 虽然我同意你的看法,但我仍然认为这是更好的行动方案。否则,链接问题就是必然的。我曾经遇到过这种情况,在使用objcopy来避免定义冲突时,我不得不对编译后的库进行修改。由于名称混淆在同一编译器的不同版本中甚至也有很大差异(在我的情况下是GCC),因此这是一个平台互操作性的噩梦。


    0

    由于名称混淆后将不同,因此链接时可能会遇到很多麻烦。是的,我知道你已经意识到了这一点,但似乎这将是一个普遍的问题。


    那就是关键点。我会将boostv1目录中的所有正则表达式源文件都用命名空间指令包装起来。 - Eclipse

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接