【问题标题】:boost::shared_ptr and std::shared_ptr co-existenceboost::shared_ptr 和 std::shared_ptr 共存
【发布时间】:2013-06-12 04:49:47
【问题描述】:

我们都知道boost和c++11都支持shared_ptr。有些编译器支持 c++11,有些不支持。我想编写我的代码,以便当编译器支持 c++11 shared_ptr 时,它使用 std::shared_ptr;如果没有,请使用 boost::shared_ptr。这方面的常见/最佳做法是什么?

让我将讨论仅限于 GCC,而不是特定版本。

【问题讨论】:

标签: c++ boost c++11 shared-ptr


【解决方案1】:

C++0x / C++11 可用性

截至今天,我知道检测 GCC 是否使用 C++0x/C++11 的唯一方法是检查预定义的宏 __GXX_EXPERIMENTAL_CXX0X__

#ifdef __GXX_EXPERIMENTAL_CXX0X__
    // C++11 code
#else
    // C++03 code
#endif

请注意,这可能会在未来发生变化(因此宏的 EXPERIMENTAL 部分)。

编辑:事实上,在@stephan 在评论中指出之前我不知道有更好的方法:

16.8/1 [cpp.predefined]

以下宏名称应由实现定义:

__cplusplus

名称__cplusplus 定义为值201103L 时 编译一个 C++ 翻译单元。157

157) 本标准的未来版本将取代 这个宏的值具有更大的值。不合格的编译器 应该使用最多五个十进制数字的值。

所以我猜你可以这样做:

#if defined(__cplusplus) && (__cplusplus >= 201103L)

但我担心这不适用于标准 C++0x GCC 版本。所以我可能会同时使用__GXX_EXPERIMENTAL_CXX0X____cplusplus

#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L))

C++0x / C++11 兼容性

然而,仅仅检测是否启用了 C++0x/C++11 支持可能并不总是足够:C++11 支持在整个 GCC 版本中发生了很大变化,不仅在核心语言级别,而且在图书馆级别也是。

我最好的选择是找到您认为可以接受 C++11 支持的最小 GCC 版本,并将上述测试与 GCC 版本测试结合起来,例如:

#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ >= 5)) // for GCC 4.7+

booststd 之间切换

现在,要在 boost::shared_ptrstd::shared_ptr 之间切换有点麻烦,因为 C++03 不支持模板化类型定义。我会在 template struct 中包含所需的定义:

#if (defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L))) \
        && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ >= 5))
    template<typename T>
    struct my_shared_ptr {
        typedef std::shared_ptr<T> type;
        // you may also want to forward make_shared etc, this is left as an exercise
    };
#else
    template<typename T>
    struct my_shared_ptr {
        typedef boost::shared_ptr<T> type;
        // you may also want to forward make_shared etc, this is left as an exercise
    };
#endif

my_shared_ptr<int>::type ptr(new int);

编辑:(再次)哎呀,我刚刚注意到 @ComicSansMS 使用简单的非模板 using 指令导入正确的 shared_ptr 的方式。不知道为什么我没有想到这一点。

不过,我仍然坚持我所描述的在 GCC 上检测 C++0x/C++11 的方式。

【讨论】:

    【解决方案2】:

    您可以将它们拉入自定义命名空间

    #ifdef HAS_STD_SHARED_PTR
        #include <memory>
        #define SHARED_PTR_NAMESPACE std
    #else
        #include <boost/shared_ptr.hpp>
        #define SHARED_PTR_NAMESPACE boost
    #endif
    
    namespace my_namespace {
         using SHARED_PTR_NAMESPACE::shared_ptr;
         using SHARED_PTR_NAMESPACE::make_shared;
    }
    
    #undef SHARED_PTR_NAMESPACE
    

    HAS_STD_SHARED_PTR 标志需要由构建环境设置。 CMake 为 detecting such features 提供了 several mechanisms,而较新的 C++ 实现还提供了 feature test macros,以便快速轻松地检测新功能。

    【讨论】:

    • 你也可以检查 C++ 版本,有一个宏:__cplusplus
    • 当然可以,但这会将您限制在一个编译器上。使用 CMake,无论您使用什么编译器工具链,您都可以依靠检测来工作。
    • @ComicSansMS: 不,C++ 的版本编码在 __cplusplus 中,这是在标准 afaik 中设置的
    • @stefan 我不确定依赖 __cplusplus 是否真的足够。编译器只能部分实现标准。更糟糕的是,这个特殊功能是库的一部分,即使编译器已经是 C++11,它仍然可能是 C++98 库。
    • 您可以(并且 IMO 应该)使用命名空间别名而不是那些定义:namespace shared_ptr_ns = boost;
    猜你喜欢
    • 2012-09-01
    • 2013-04-16
    • 2011-09-27
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多