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

如何通用检测std::unique_ptr及实现空指针变体判断?

一、通用检测std::unique_ptr(支持const&和自定义删除器)

要判断一个类型是否为std::unique_ptr(包含带自定义删除器、const引用等变体),可以通过类型 trait实现:

#include <memory>
#include <type_traits>

// 基础模板:匹配非unique_ptr类型
template<typename T>
struct is_unique_ptr : std::false_type {};

// 偏特化:匹配任意T和Deleter的std::unique_ptr
template<typename T, typename Deleter>
struct is_unique_ptr<std::unique_ptr<T, Deleter>> : std::true_type {};

// 处理const、volatile、引用修饰的情况
template<typename T>
struct is_unique_ptr<const T> : is_unique_ptr<T> {};

template<typename T>
struct is_unique_ptr<volatile T> : is_unique_ptr<T> {};

template<typename T>
struct is_unique_ptr<const volatile T> : is_unique_ptr<T> {};

template<typename T>
struct is_unique_ptr<T&> : is_unique_ptr<T> {};

template<typename T>
struct is_unique_ptr<T&&> : is_unique_ptr<T> {};

// 辅助变量模板,简化使用
template<typename T>
constexpr bool is_unique_ptr_v = is_unique_ptr<T>::value;

测试示例

#include <iostream>

int main() {
    std::unique_ptr<int> up;
    const std::unique_ptr<int, std::default_delete<int>>& cup_ref = up;
    
    std::cout << std::boolalpha;
    std::cout << is_unique_ptr_v<decltype(up)> << "\n";          // 输出true
    std::cout << is_unique_ptr_v<decltype(cup_ref)> << "\n";    // 输出true
    std::cout << is_unique_ptr_v<int*> << "\n";                 // 输出false
    std::cout << is_unique_ptr_v<std::shared_ptr<int>> << "\n"; // 输出false
    return 0;
}

二、一次性检测所有标准智能指针

如果需要判断类型是否为任意标准智能指针(std::unique_ptr/std::shared_ptr/std::weak_ptr),可以用std::disjunction组合多个trait:

// 检测std::shared_ptr的trait
template<typename T>
struct is_shared_ptr : std::false_type {};

template<typename T>
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};

// 检测std::weak_ptr的trait
template<typename T>
struct is_weak_ptr : std::false_type {};

template<typename T>
struct is_weak_ptr<std::weak_ptr<T>> : std::true_type {};

// 处理cv和引用修饰的特化(和is_unique_ptr逻辑一致,此处省略重复代码)
template<typename T>
struct is_shared_ptr<const T> : is_shared_ptr<T> {};
template<typename T>
struct is_weak_ptr<const T> : is_weak_ptr<T> {};

// 统一的智能指针检测trait
template<typename T>
struct is_smart_ptr : std::disjunction<
    is_unique_ptr<T>,
    is_shared_ptr<T>,
    is_weak_ptr<T>
> {};

// 辅助变量模板
template<typename T>
constexpr bool is_smart_ptr_v = is_smart_ptr<T>::value;

三、实现IsEmptyVariantOfPointers的enable_if条件

要让函数仅在std::variant<T...>的所有参数都是可与nullptr比较的指针类型(裸指针、unique_ptr、shared_ptr)时实例化,需要两步:

步骤1:实现单个类型的空指针兼容检测

#include <utility> // 用于std::void_t

// 基础模板:默认不兼容
template<typename T, typename = void>
struct is_nullptr_compatible : std::false_type {};

// 匹配裸指针
template<typename T>
struct is_nullptr_compatible<T*, void> : std::true_type {};

// 匹配能与nullptr比较的类型(如智能指针)
template<typename T>
struct is_nullptr_compatible<T, std::void_t<decltype(std::declval<T>() == nullptr)>> : std::true_type {};

// 辅助变量模板
template<typename T>
constexpr bool is_nullptr_compatible_v = is_nullptr_compatible<T>::value;

步骤2:填充enable_if条件

用std::conjunction_v确保variant的所有参数都满足空指针兼容:

#include <variant>

template<typename... T>
std::enable_if_t<std::conjunction_v<is_nullptr_compatible<T>...>, bool>
IsEmptyVariantOfPointers(const std::variant<T...>& variant)
{
    bool emptyVariant = true;
    std::visit([&emptyVariant](auto&& arg)
    {
        emptyVariant = (arg == nullptr);
    }, variant);

    return emptyVariant;
}

测试示例

int main() {
    std::variant<int*, std::unique_ptr<int>, std::shared_ptr<int>> var1;
    std::variant<int*, std::unique_ptr<int, std::default_delete<int>>> var2;
    std::variant<int, std::string> var3; // 非指针类型,函数不会实例化

    var1 = nullptr;
    std::cout << IsEmptyVariantOfPointers(var1) << "\n"; // 输出true

    var2 = std::make_unique<int>(42);
    std::cout << IsEmptyVariantOfPointers(var2) << "\n"; // 输出false

    // IsEmptyVariantOfPointers(var3); // 编译错误,符合预期
    return 0;
}

补充说明

  • std::void_t用于SFINAE检测:如果arg == nullptr是合法表达式,则特化版本生效,判定为兼容。
  • std::conjunction_v会检查所有模板参数是否都满足条件,只要有一个不满足,函数就不会被实例化。
  • 该方案无需重载模板函数,通过trait统一判断所有合法类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:50:22