enable_if转换构造函数(静态强制转换,is_base_of)

enable_if on conversion constructor (static cast, is_base_of)

本文关键字:转换 is base of 静态 if 构造函数 enable      更新时间:2023-10-16

我正在研究共享指针的实现。(使用C++17,以防万一(

唯一的问题是转换构造函数。我希望能够将smart_ptr静态转换为基本类型的smart_ptr。

template<typename U>
inline smart_ptr(const smart_ptr<U>& rhs)
{
...
}

它有效,但它也会尝试将smart_ptr转换为任何其他类型的smart_ptr。例如,如果我有一个重载函数,可以采用不同类型的不相关类型的smart_ptr,则会收到有关不明确重载的编译器错误。因此,如果 U 是 T 的派生类,我只想要从 smart_ptr -> smart_ptr 进行转换。

这看起来应该有效。它可以编译,但它做相反的事情。它可以防止有效的静态向上转换工作,但仍允许对不相关的类型进行转换:

template<typename U>
inline local_shared_ptr(typename enable_if<is_base_of<T,U>::value, const  local_shared_ptr<U>&>::type rhs)
{
...
}

编辑:

让它工作,感谢您的帮助。我选择jarod的解决方案,因为我发现template <typename U, enable_if_t<is_base_of<T,U>::value, int> = 0>最简洁的。我没有意识到SFINAE可以如此简洁。

另外,由于内森提到了它:

有趣的是,我遇到的问题之一是,我希望在右侧类型相同时调用模板复制构造函数。显然,编译器不认为它是复制构造函数的实现,而是调用了自动生成的复制构造函数。移动构造函数和运算符=的相同问题。不确定这是否是MSVC2019的错误。

U是不可推导的

template<typename U>
local_shared_ptr(enable_if_t<is_base_of<T,U>::value, const  local_shared_ptr<U>&> rhs)
{
// ...
}

由于它是一个构造函数,您甚至无法显式提供模板。 所以那个构造函数是无用的。

您可以改用:

  • 默认参数(与您的尝试 IMO 最相似(:

    template <typename U>
    local_shared_ptr(const local_shared_ptr<U>& rhs, enable_if_t<is_base_of<T,U>::value, int> = 0)
    {
    // ...
    }
    
  • 默认模板参数(首选方式(:

    template <typename U, enable_if_t<is_base_of<T,U>::value, int> = 0>
    local_shared_ptr(const local_shared_ptr<U>& rhs)
    {
    // ...
    }
    

当你使用构造函数时,你不能使用返回值。

enable_if放在模板参数列表中,例如

template<typename U, std::enable_if_t<std::is_base_of_v<T, U>, bool> = true>
inline smart_ptr(const smart_ptr<U>& rhs)
{
}

现在,只有当UT,或者从T派生时,才会调用它。 如果您不想使用它,如果U == T那么您可以使用

template<typename U, std::enable_if_t<std::is_base_of_v<T, U> && !std::is_same_v<T, U>, bool> = true>
inline smart_ptr(const smart_ptr<U>& rhs)
{
}