说明std :: is_base_of的可能实现

Explanation of possible implementation of std::is_base_of

本文关键字:实现 base std is 说明 of      更新时间:2023-10-16
1.  template <typename Base> std::true_type is_base_of_test_func( Base* );
2.  template <typename Base> std::false_type is_base_of_test_func( void* );
3.  template <typename Base, typename Derived>
    using pre_is_base_of = decltype( is_base_of_test_func<Base>( std::declval<Derived*>() ) );
4.  template <typename Base, typename Derived, typename = void>
    struct pre_is_base_of2 : public std::true_type {};
5.  template<typename ...> using void_t = void;
6.  template <typename Base, typename Derived>
    struct pre_is_base_of2<Base, Derived, void_t<pre_is_base_of<Base, Derived>>> : public pre_is_base_of<Base, Derived>{};

7.  template <typename Base, typename Derived>
    struct is_base_of : public std::conditional_t<std::is_class<Base>::value && std::is_class<Derived>::value,
                                                  pre_is_base_of2<Base, Derived>,
                                                  std::false_type>
    {
    };

行1.和2.几乎是直截了当的。

,但是,第3行:using有极度模糊,因为我不能简单地替换pre_is_base_of的所有发生及其定义。Ergo,using并不是文档所说的。它也涉及一些宗教。如果我没有错,则pre_is_base_of的用法应返回std::true_typestd::false_type
void_t方面,我同样迷路了。那条线会做什么样的魔术?
pre_is_base_of2的两种实现都不应采用3种类型?第6行中继承的意义是什么?可能还有更多,但现在就停止。

我需要对这里涉及的魔术的一些详细解释。基本上我正在尝试了解该代码的工作原理。

编辑:当默认值问我有什么错误时,我替换了pre_is_base_of的每一次出现,现在没有错误。

  1. template <typename Base> std::true_type is_base_of_test_func( Base* );

当参数是基础或源自基础的基础时,此过载具有最高优先级

  1. template <typename Base> std::false_type is_base_of_test_func( void* );

此超载将与任何类型匹配,优先级最低

  1. template <typename Base, typename Derived> using pre_is_base_of = decltype( is_base_of_test_func<Base>( std::declval<Derived*>() ) );

pre_is_base_of将通过用指针拨打Derived来调用is_base_of_test_func返回的类型。如果Derived是从基数派生的,它将返回std :: true_type,否则将选择void* Overload,并且它将返回一个std :: false_type。现在,我们将函数调用结果转换为类型。

  1. template <typename Base, typename Derived, typename = void> struct pre_is_base_of2 : public std::true_type {};

一般情况,这将是一个true_type。由于第三模板参数被默认,因此当未创建其他专业化时,这将是定义的类的版本。

  1. template<typename ...> using void_t = void;

这是进行enable_if的一种更简单的方法。void_t<X>仅在X是合法类型的情况下才是类型。

  1. template <typename Base, typename Derived> struct pre_is_base_of2<Base, Derived, void_t<pre_is_base_of<Base, Derived>>> : public pre_is_base_of<Base, Derived>{};

如果void_t是法定类型(即pre_is_base_of<Base>(Derived*)是一个有效的表达式,这将是pre_is_base_of2的专业化,它将评估上述调用测试功能的声明。仅当pre_is_base_of<Base,Derived>是有效的类型时才选择它(即,是否存在调用测试功能(

  1. template <typename Base, typename Derived> struct is_base_of : public std::conditional_t<std::is_class<Base>::value && std::is_class<Derived>::value, pre_is_base_of2<Base, Derived>, std::false_type> { };

本质上是说:

IF Base and Value are classes AND void_t<decltype(is_base_of_test_func<Base>(Derived*))> is a type
THEN
    select the type of pre_is_base_of2<Base, Derived, void_t<...is the expression legal?...>>
ELSE
    select false_type        

更新:

希望这个小型演示程序能够提供一些清晰度:

#include <type_traits>
#include <iostream>
template<class...> using void_t = void;
// this expands in any case where no second type is provided
template<class T, typename = void> struct does_he_take_sugar : std::false_type {};
// the specialisation can only be valid when void_t<expr> evaluates to a type.
// i.e. when T has a member function called take_sugar
template<class T> struct does_he_take_sugar<T, void_t<decltype(std::declval<T>().take_sugar())>> : std::true_type {};

struct X {
    int take_sugar();
};
struct Y {
    int does_not();
};
int main()
{
    // X::take_sugar is a function therefore void_t<decltype(...X)> will evaluate to void
    std::cout << does_he_take_sugar<X>::value << std::endl;
    // Y::take_sugar is not a function therefore void_t<decltype(...Y)> will not evaluate at all
    std::cout << does_he_take_sugar<Y>::value << std::endl;
    // int::take_sugar is not even valid c++ void_t<decltype(...int)> will not evaluate at all
    std::cout << does_he_take_sugar<int>::value << std::endl;
}

用于实现的骨架。在当前形式中,它不考虑POD类型。

template <class Base, class Derived, class = void>
struct is_base_of
{
    static const bool value = false;
};
template <class Base, class Derived>
struct is_base_of<Base, Derived, typename enable_if<(Base*)(Derived*)nullptr == (Derived*)nullptr, void>::type>
{
    static const bool value = true;
};

此比较可以解决:(Base*)(Derived*)nullptr == (Derived*)nullptr。仅当DerivedBase继承时,该比较才有效,否则该表达式无效,并且导致Sfinae。