如何条件声明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
相关产品推荐
相关产品推荐

