不同条件下__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
相关产品推荐
相关产品推荐

