You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何条件声明make_unique:STL已提供则using,否则自行定义?

解决方案

要实现你想要的逻辑,既可以用C11的SFINAE特性精准检测std::make_unique是否存在,也可以通过预处理器宏直接判断C版本,下面分别给出两种可行方案:

方案一:SFINAE特性检测(兼容特殊编译器扩展)

先定义类型特性来判断std::make_unique是否可调用,再通过std::enable_if控制模板实例化:

#include <memory>
#include <type_traits>

// 内部检测逻辑
namespace detail {
    // 尝试匹配非数组版std::make_unique
    template<typename T, typename... Args>
    auto test_make_unique(int) -> decltype(std::make_unique<T>(std::declval<Args>()...), std::true_type{});

    // 匹配失败时的 fallback
    template<typename...>
    std::false_type test_make_unique(...);

    // 尝试匹配数组版std::make_unique
    template<typename T>
    auto test_make_unique_array(int) -> decltype(std::make_unique<T[]>(), std::true_type{});

    template<typename T>
    std::false_type test_make_unique_array(...);
}

// 定义检测特性
template<typename T, typename... Args>
struct has_std_make_unique : decltype(detail::test_make_unique<T, Args...>(0)) {};

template<typename T>
struct has_std_make_unique_array : decltype(detail::test_make_unique_array<T>(0)) {};

// 目标命名空间实现
namespace notstd {
    // 标准库版本存在时,转发调用
    template<typename T, typename... Args, typename = typename std::enable_if<has_std_make_unique<T, Args...>::value>::type>
    auto make_unique(Args&&... args) -> decltype(std::make_unique<T>(std::forward<Args>(args)...)) {
        return std::make_unique<T>(std::forward<Args>(args)...);
    }

    // 标准库版本不存在时,使用自定义实现
    template<typename T, typename... Args, typename = typename std::enable_if<!has_std_make_unique<T, Args...>::value>::type>
    std::unique_ptr<T> make_unique(Args&&... args) {
        return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
    }

    // 数组类型兼容处理
    template<typename T, typename = typename std::enable_if<has_std_make_unique_array<T>::value>::type>
    auto make_unique(std::size_t size) -> decltype(std::make_unique<T[]>(size)) {
        return std::make_unique<T[]>(size);
    }

    template<typename T, typename = typename std::enable_if<!has_std_make_unique_array<T>::value>::type>
    std::unique_ptr<T[]> make_unique(std::size_t size) {
        return std::unique_ptr<T[]>(new typename std::remove_extent<T>::type[size]());
    }
}

方案二:预处理器宏判断C++版本(简洁直接)

因为std::make_unique是C++14正式引入的特性,直接通过__cplusplus宏判断版本更简单:

#include <memory>
#include <type_traits>

namespace notstd {
#if __cplusplus >= 201402L
    // C++14及以上,直接引入标准库版本
    using std::make_unique;
#else
    // C++11及以下,自定义实现
    template<class T, class... Args>
    std::unique_ptr<T> make_unique(Args&&... args) {
        return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
    }

    // 补充数组版本实现
    template<class T>
    std::unique_ptr<T[]> make_unique(std::size_t size) {
        return std::unique_ptr<T[]>(new typename std::remove_extent<T>::type[size]());
    }
#endif
}

两种方案对比

  • SFINAE方案更精准,能兼容部分在C++11模式下提供std::make_unique扩展的编译器;
  • 预处理器方案更简洁直观,适合大多数常规场景。

内容的提问来源于stack exchange,提问作者Vinny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 07:46:22