说明std :: is_base_of的可能实现
Explanation of possible implementation of 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.几乎是直截了当的。
using
有极度模糊,因为我不能简单地替换pre_is_base_of
的所有发生及其定义。Ergo,using
并不是文档所说的。它也涉及一些宗教。pre_is_base_of
的用法应返回std::true_type
或std::false_type
。在
void_t
方面,我同样迷路了。那条线会做什么样的魔术?pre_is_base_of2
的两种实现都不应采用3种类型?第6行中继承的意义是什么?可能还有更多,但现在就停止。
我需要对这里涉及的魔术的一些详细解释。基本上我正在尝试了解该代码的工作原理。
编辑:当默认值问我有什么错误时,我替换了pre_is_base_of
的每一次出现,现在没有错误。
template <typename Base> std::true_type is_base_of_test_func( Base* );
当参数是基础或源自基础的基础时,此过载具有最高优先级
template <typename Base> std::false_type is_base_of_test_func( void* );
此超载将与任何类型匹配,优先级最低
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。现在,我们将函数调用结果转换为类型。
template <typename Base, typename Derived, typename = void> struct pre_is_base_of2 : public std::true_type {};
一般情况,这将是一个true_type。由于第三模板参数被默认,因此当未创建其他专业化时,这将是定义的类的版本。
template<typename ...> using void_t = void;
这是进行enable_if的一种更简单的方法。void_t<X>
仅在X是合法类型的情况下才是类型。
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>
是有效的类型时才选择它(即,是否存在调用测试功能(
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
。仅当Derived
从Base
继承时,该比较才有效,否则该表达式无效,并且导致Sfinae。
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 使用GSoap实现ONVIF
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 用于AVX的ln(x)的实现,m256
- 如何在C++实现继承并解决错误"parent class is not accessible base of child class"?
- 实现观察者模式的问题:"Member reference base type ________ is not a structure or union"