【问题标题】:understanding std::is_base_of possible implementation from cppreference从 cppreference 理解 std::is_base_of 可能的实现
【发布时间】:2022-10-23 20:48:49
【问题描述】:

这里我们有来自cppreference.comis_base_of 模板实现:

namespace details {
     template <typename B>
     std::true_type test_pre_ptr_convertible(const B*);      //1
     template <typename>
     std::false_type test_pre_ptr_convertible(const void*);  //2

     template <typename, typename>
     auto test_pre_is_base_of(...)->std::true_type;          //3
     template <typename B, typename D>
     auto test_pre_is_base_of(int) ->
         decltype(test_pre_ptr_convertible<B>(static_cast<D*>(nullptr))); 
 }

template <typename Base, typename Derived>
 struct is_base_of :
     std::integral_constant<
     bool,
     std::is_class<Base>::value&& std::is_class<Derived>::value&&
     decltype(details::test_pre_is_base_of<Base, Derived>(0))::value
     > { };

还有一些私人的遗产:

class A {};
class B : A {};

is_base_of&lt;A,B&gt;::value 给出真实的声明号。 3是最好的搭配。声明编号1 作为候选者失败(传递了一个指向私有子类对象的指针)和声明号。 2 被忽略。但为什么? void* 不是每个指针类型的好匹配吗?如果声明没有。 3 未提供代码无法编译。我的问题是为什么声明没有。 3 需要提供此代码才能成功编译吗?为什么声明没有。 1和没有。 2还不够?

【问题讨论】:

    标签: c++ overloading template-meta-programming function-templates-overloading


    【解决方案1】:

    过载解决方案忽略了可访问性,以决定哪些候选者是可行的并选择最佳候选者。

    如果DB 的派生类(无论可访问性如何),那么//1 总是可行的,并且比//2 更适合重载解决方案(这也是可行的),重载解决方案将选择前者。

    如果//1 被选为最佳候选且B 不是D 的公共基础,那么所需的参数隐式转换将失败,因为B 不是可访问的基础。但这已经是在完成重载解决之后。将不会尝试回退到“第二好的”重载//2

    由于对test_pre_ptr_convertible 的调用因此无效,因此整个程序通常是格式错误的。但是,这里的调用是函数模板的返回类型,因此 SFINAE 适用,这意味着重载

    template <typename B, typename D>
    auto test_pre_is_base_of(int) ->
        decltype(test_pre_ptr_convertible<B>(static_cast<D*>(nullptr)));
    

    对于来自is_base_of 的调用根本不可行,而test_pre_is_base_of 的唯一剩余重载是//3,然后选择它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 2016-06-24
      相关资源
      最近更新 更多