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

不同条件下__uniq_ptr_impl的pointer定义匹配哪个_Ptr模板?

__uniq_ptr_impl中_Ptr模板的匹配规则解析

先看原代码:

template <typename _Tp, typename _Dp>
class __uniq_ptr_impl
{
    template <typename _Up, typename _Ep, typename = void>
    struct _Ptr
    {
      using type = _Up*;
    };

    template <typename _Up, typename _Ep>
    struct
    _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
    {
      using type = typename remove_reference<_Ep>::type::pointer;
    };

public:
    using _DeleterConstraint = enable_if<
        __and_<__not_<is_pointer<_Dp>>,
        is_default_constructible<_Dp>>::value>;

    using pointer = typename _Ptr<_Tp, _Dp>::type; 
    
//omit code below ...

}

这里核心靠C++的**SFINAE(替换失败并非错误)**规则决定_Ptr的匹配逻辑,分两种情况:

  • 情况1:删除器自带pointer类型别名
    当传入的删除器_Dp(对应模板里的_Ep),移除引用后(remove_reference<_Ep>::type)存在pointer这个类型别名时,__void_t<typename remove_reference<_Ep>::type::pointer>会合法推导为void,刚好匹配偏特化模板的第三个参数(主模板第三个参数默认是void)。此时编译器优先选偏特化版本的_Ptr,最终pointer类型就是删除器里定义的pointer。

    举个例子:

    struct CustomDeleter {
        using pointer = void*; // 自定义pointer类型
        void operator()(void* p) const { /* 自定义销毁逻辑 */ }
    };
    

    这时_Ptr<MyType, CustomDeleter>会匹配偏特化,pointer就是CustomDeleter::pointer。

  • 情况2:删除器没有pointer类型别名
    如果删除器移除引用后不存在pointer类型别名,__void_t<...>的推导会失败,根据SFINAE规则,这个偏特化模板会被编译器忽略,转而使用主模板。此时pointer类型就是_Tp*(也就是主模板里的_Up*)。

    比如用默认的std::default_delete<int>,它没有自定义pointer成员,这时候pointer就会是int*。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:22:46