std :: is_base_of的可能实现的说明 [英] Explanation of possible implementation of std::is_base_of

查看:75
本文介绍了std :: is_base_of的可能实现的说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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行:使用含糊不清,因为我不能简单地将每次出现的 pre_is_base_of 替换为其定义.嗯, using 并不是文档中所说的.如果我没记错的话, pre_is_base_of 的用法应返回 std :: true_type std :: false_type.
当涉及到 void_t 时,我同样迷失了.该行将执行哪种魔术?
pre_is_base_of2 的两种实现都不应采用3种类型吗?第6行的继承点是什么?可能还有更多,但让我们现在停止.

Lines 1. and 2. are pretty much straight forward. But, line 3: the using there is extremely vague, because I cannot simply replace every occurrence of pre_is_base_of with its definition. Ergo, the using is not really what the documentation says. It involves some religion as well. If I'm not wrong, the usage of pre_is_base_of should return std::true_type or std::false_type.
I'm equally lost when it comes to void_t. What kind of magic will that line do?
Shouldn't both implementations of pre_is_base_of2 take 3 types? What's the point of inheritance in line 6? There is probably more, but lets stop now.

在这里,我需要一些有关魔术的详细解释.基本上,我试图了解该代码的工作原理.

I would need some detailed explanation on magic involved here. Basically I'm trying to understand how that code works.

默认问我是什么错误时,我替换了每次出现的 pre_is_base_of 现在没有错误.

When default asked me what's the error, I replaced every occurrence of pre_is_base_of and now there is no error.

推荐答案

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

当参数是Base或从Base派生时,此重载具有最高优先级

When the argument is a Base, or derived from Base, this overload has the highest priority

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

此重载将匹配优先级最低的任何类型

this overload will match any type, with the lowest priority

  1. 模板< typename Base,派生的typename>使用pre_is_base_of = decltype(is_base_of_test_func< Base>(std :: declval< Derived *>()));

通过调用 is_base_of_test_func 和指向 Derived 的指针,

pre_is_base_of将成为返回的类型.如果 Derived 是从Base派生的,它将返回std :: true_type,否则将选择void *重载并将返回std :: false_type.现在,我们已将函数调用结果转换为类型.

pre_is_base_of will become the type returned by calling is_base_of_test_func with a pointer to Derived. If Derived is derived from Base, it will return std::true_type, otherwise the void* overload will be selected and it will return a std::false_type. Now we have converted a function call result into a type.

  1. template< typename Base,派生的typename,typename = void>struct pre_is_base_of2:公共std :: true_type {};

一般情况下,这将是true_type.由于默认使用第三个模板参数,因此它将是未创建其他任何专业化时定义的类的版本.

General case, this will be a true_type. Since the 3rd template argument is defaulted, this will be the version of the class defined when no other specialisation is created.

  1. template< typename ...>使用void_t = void;

这是启用enable_if的一种更简单的方法. void_t< X> 仅在X是合法类型时才是类型.

This is an easier way of doing enable_if. void_t<X> will only be a type if X is a legal type.

  1. 模板< typename Base,派生的typename>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 的专业化版本.code>,它将评估为调用测试函数的十进制类型.仅当 pre_is_base_of< Base,Derived> 是有效类型(即存在对测试函数的调用)时,才会选择)

if void_t is a legal type (i.e. pre_is_base_of<Base>(Derived*) is a valid expression, this will be the specialisation of pre_is_base_of2, which will evaluate to the decltype of calling the test function, above. It will only be selected if pre_is_base_of<Base,Derived> is a valid type (i.e. there exists a call to the test function)

  1. 模板< typename Base,派生的typename>struct is_base_of:公共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        

更新:

希望这个小演示程序可以提供一些清晰度:

Hopefully this little demo program will provide some clarity:

#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;
}

这篇关于std :: is_base_of的可能实现的说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆