栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

type

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

type

文章目录

一、源码二、源码解析

1.remove_extent:移除数组的第一层维度2.remove_all_extents: 移除所有数组维度3.remove_pointer: 移除指针类型4.add_pointer : 添加指针类型5.is_array: 判断是否是数组类型6.is_reference:是否是引用类型。is_lvalue_reference: 左值引用,is_rvalue_reference: 右值引用7.is_pointer: 是否是指针类型8.is_null_pointer: 判断指针是否是空,利用is_same9.判断是否是基本类型(整形,浮点数,void,nullptr)10.is_union:判断是不是内联结构,is_class:判断是不是类对象。is_convertible:判断能否转化从from到to。is_enum:判断是不是枚举类型(只能看到定义。没有找到具体实现。待日后找到后补上)

一、源码

老规矩先放源码

template 
struct remove_extent { // remove array extent
    using type = _Ty;
};

template 
struct remove_extent<_Ty[_Ix]> {
    using type = _Ty;
};

template 
struct remove_extent<_Ty[]> {
    using type = _Ty;
};

template 
using remove_extent_t = typename remove_extent<_Ty>::type;

template 
struct remove_all_extents { // remove all array extents
    using type = _Ty;
};

template 
struct remove_all_extents<_Ty[_Ix]> {
    using type = typename remove_all_extents<_Ty>::type;
};

template 
struct remove_all_extents<_Ty[]> {
    using type = typename remove_all_extents<_Ty>::type;
};

template 
using remove_all_extents_t = typename remove_all_extents<_Ty>::type;

template 
struct remove_pointer {
    using type = _Ty;
};

template 
struct remove_pointer<_Ty*> {
    using type = _Ty;
};

template 
struct remove_pointer<_Ty* const> {
    using type = _Ty;
};

template 
struct remove_pointer<_Ty* volatile> {
    using type = _Ty;
};

template 
struct remove_pointer<_Ty* const volatile> {
    using type = _Ty;
};

template 
using remove_pointer_t = typename remove_pointer<_Ty>::type;

template 
struct _Add_pointer { // add pointer (pointer type cannot be formed)
    using type = _Ty;
};

template 
struct _Add_pointer<_Ty, void_t*>> { // (pointer type can be formed)
    using type = remove_reference_t<_Ty>*;
};

template 
struct add_pointer {
    using type = typename _Add_pointer<_Ty>::type;
};

template 
using add_pointer_t = typename _Add_pointer<_Ty>::type;

template 
_INLINE_VAR constexpr bool is_array_v = false; // determine whether type argument is an array

template 
_INLINE_VAR constexpr bool is_array_v<_Ty[_Nx]> = true;

template 
_INLINE_VAR constexpr bool is_array_v<_Ty[]> = true;

template 
struct is_array : bool_constant> {};

#if _HAS_CXX20
template 
inline constexpr bool is_bounded_array_v = false;

template 
inline constexpr bool is_bounded_array_v<_Ty[_Nx]> = true;

template 
struct is_bounded_array : bool_constant> {};

template 
inline constexpr bool is_unbounded_array_v = false;

template 
inline constexpr bool is_unbounded_array_v<_Ty[]> = true;

template 
struct is_unbounded_array : bool_constant> {};
#endif // _HAS_CXX20

template 
_INLINE_VAR constexpr bool is_lvalue_reference_v = false; // determine whether type argument is an lvalue reference

template 
_INLINE_VAR constexpr bool is_lvalue_reference_v<_Ty&> = true;

template 
struct is_lvalue_reference : bool_constant> {};

template 
_INLINE_VAR constexpr bool is_rvalue_reference_v = false; // determine whether type argument is an rvalue reference

template 
_INLINE_VAR constexpr bool is_rvalue_reference_v<_Ty&&> = true;

template 
struct is_rvalue_reference : bool_constant> {};

template 
_INLINE_VAR constexpr bool is_reference_v = false; // determine whether type argument is a reference

template 
_INLINE_VAR constexpr bool is_reference_v<_Ty&> = true;

template 
_INLINE_VAR constexpr bool is_reference_v<_Ty&&> = true;

template 
struct is_reference : bool_constant> {};

template 
_INLINE_VAR constexpr bool is_pointer_v = false; // determine whether _Ty is a pointer

template 
_INLINE_VAR constexpr bool is_pointer_v<_Ty*> = true;

template 
_INLINE_VAR constexpr bool is_pointer_v<_Ty* const> = true;

template 
_INLINE_VAR constexpr bool is_pointer_v<_Ty* volatile> = true;

template 
_INLINE_VAR constexpr bool is_pointer_v<_Ty* const volatile> = true;

template 
struct is_pointer : bool_constant> {};

template 
_INLINE_VAR constexpr bool is_null_pointer_v =
    is_same_v, nullptr_t>; // determine whether _Ty is cv-qualified nullptr_t

template 
struct is_null_pointer : bool_constant> {};

template 
struct is_union : bool_constant<__is_union(_Ty)> {}; // determine whether _Ty is a union

template 
_INLINE_VAR constexpr bool is_union_v = __is_union(_Ty);

template 
struct is_class : bool_constant<__is_class(_Ty)> {}; // determine whether _Ty is a class

template 
_INLINE_VAR constexpr bool is_class_v = __is_class(_Ty);

template 
_INLINE_VAR constexpr bool is_fundamental_v = is_arithmetic_v<_Ty> || is_void_v<_Ty> || is_null_pointer_v<_Ty>;

template 
struct is_fundamental : bool_constant> {}; // determine whether _Ty is a fundamental type

template 
struct is_convertible : bool_constant<__is_convertible_to(_From, _To)> {
    // determine whether _From is convertible to _To
};

template 
_INLINE_VAR constexpr bool is_convertible_v = __is_convertible_to(_From, _To);

template 
struct is_enum : bool_constant<__is_enum(_Ty)> {}; // determine whether _Ty is an enumerated type

template 
_INLINE_VAR constexpr bool is_enum_v = __is_enum(_Ty);
二、源码解析 1.remove_extent:移除数组的第一层维度

例如remove_extent _Ty = int[2],第一层维度int[10]被擦除了,剩下int[2]

//定义基础类型
template 
struct remove_extent { // remove array extent
    using type = _Ty;
};
//对上述特化,利用模板特化反向推导出Ix的大小,并且移除掉[Ix]。
//例如传入的是int[10][2]最后剩下的类型也就是_Ty的类型是int[2]
//特化擦除会将已有的擦除掉,因为[Ix]也就是[10]已经被定义了,剩下的_Ty = int[2]
template 
struct remove_extent<_Ty[_Ix]> {
    using type = _Ty;
};
//当传入的是没有指定大小的数组例如int[],这类的
template 
struct remove_extent<_Ty[]> {
    using type = _Ty;
};
//重新定义类型。注意typename显示声明一个类型时使用
template 
using remove_extent_t = typename remove_extent<_Ty>::type;

测试demo

#include 
using namespace std;

template
struct MyStruct
{
    using type = T;
};

template
struct MyStruct
{
    constexpr static size_t value = Ix;
    using type = T;
};

template
struct MyStruct
{
    using type = T;
};

int main()
{
    MyStruct::type a;
    MyStruct::type b;
    MyStruct::type c;
    MyStruct::type d;
    auto e = MyStruct::value;
    MyStruct::type f;
    return 0;
}


我还是喜欢根据现象反推导实际的实现。根据定义看现象,容易陷入误区,还是实践靠谱。

根据demo测试尝试推测模板类型推导:实际就是有啥擦除啥,你自己特化了什么他就把那部分去除掉,感觉编译器实现的方式就是字符串匹配。找到最合适那个匹配到,已有的去除掉。就像int【10】【2】最后被提取了【10】,其实我以为会是【2】被提取走,剩下int【10】,但实际是先匹配的第一层。直接看结果比看啥定义靠谱。

2.remove_all_extents: 移除所有数组维度

实际就是递归调用,直到所有数组都被擦除,然后返回最后的类型。

typename remove_all_extents<_Ty>::type

就是递归调用

type=::type,type=::type, type=::type=int

template 
struct remove_all_extents { // remove all array extents
    using type = _Ty;
};

template 
struct remove_all_extents<_Ty[_Ix]> {
    //和上述这里不一致。
    //这里递归调用自身,将全部数组擦除
    using type = typename remove_all_extents<_Ty>::type;
};

template 
struct remove_all_extents<_Ty[]> {
    //和上述这里不一致。
    //这里递归调用自身,将全部数组擦除
    using type = typename remove_all_extents<_Ty>::type;
};
//重新定义类型。注意typename显示声明一个类型时使用
template 
using remove_all_extents_t = typename remove_all_extents<_Ty>::type;
3.remove_pointer: 移除指针类型
//这对大家来说看的实在太多了。就是利用特化移除掉某个属性。这类的基本实现都一样。
template 
struct remove_pointer {
    using type = _Ty;
};
//特化,擦除掉指针类型
template 
struct remove_pointer<_Ty*> {
    using type = _Ty;
};
//特化,擦除掉const指针类型
template 
struct remove_pointer<_Ty* const> {
    using type = _Ty;
};
//特化,擦除掉volatile指针类型
template 
struct remove_pointer<_Ty* volatile> {
    using type = _Ty;
};
//特化,擦除掉const volatile指针类型
template 
struct remove_pointer<_Ty* const volatile> {
    using type = _Ty;
};
//新定义一个类型,方便使用
template 
using remove_pointer_t = typename remove_pointer<_Ty>::type;
4.add_pointer : 添加指针类型

与之前说过的添加引用类型类似

//普通模板+第二个参数是void因为特化要单参数使用void_t
template 
struct _Add_pointer { // add pointer (pointer type cannot be formed)
    using type = _Ty;
};
//remove_reference_t移除引用类型,之前讲过,就如上述实现方式一直,利用特化擦除掉引用
//void_t*>擦除掉引用,后判断该类型能否定义为指针类型。不能则调用失败。
template 
struct _Add_pointer<_Ty, void_t*>> { // (pointer type can be formed)
    using type = remove_reference_t<_Ty>*;
};
//中转战一样,又定义了一次。应该是为了隐藏实现。便于查看
template 
struct add_pointer {
    using type = typename _Add_pointer<_Ty>::type;
};
//_t类型,统一格式利于使用。
template 
using add_pointer_t = typename _Add_pointer<_Ty>::type;
5.is_array: 判断是否是数组类型

和之前数组类型擦除类似,不过那个是直接擦除重定义一个类型,这个是判断,特化的变量

//普通模板,也就是最后的出口。当所有特化都不满足才会被匹配到
template 
_INLINE_VAR constexpr bool is_array_v = false; // determine whether type argument is an array
//是数组类型则能跟此特化匹配到,最后结果为true;
template 
_INLINE_VAR constexpr bool is_array_v<_Ty[_Nx]> = true;
//是数组类型则能跟此特化匹配到,最后结果为true;
template 
_INLINE_VAR constexpr bool is_array_v<_Ty[]> = true;
//定义一个bool_constant类型,判断是否是数组,最后会是true_type, false_type
template 
struct is_array : bool_constant> {};
//就是将是否指定了大小分离开了,分成两个进行判断了
#if _HAS_CXX20
template 
inline constexpr bool is_bounded_array_v = false;
//指定了大小
template 
inline constexpr bool is_bounded_array_v<_Ty[_Nx]> = true;

template 
struct is_bounded_array : bool_constant> {};

template 
inline constexpr bool is_unbounded_array_v = false;
//没有指定了大小
template 
inline constexpr bool is_unbounded_array_v<_Ty[]> = true;

template 
struct is_unbounded_array : bool_constant> {};
#endif // _HAS_CXX20
6.is_reference:是否是引用类型。is_lvalue_reference: 左值引用,is_rvalue_reference: 右值引用

这个实现看的太多了,都是利用特化进行判断类型。

template 
_INLINE_VAR constexpr bool is_lvalue_reference_v = false; // determine whether type argument is an lvalue reference

template 
_INLINE_VAR constexpr bool is_lvalue_reference_v<_Ty&> = true;

template 
struct is_lvalue_reference : bool_constant> {};

template 
_INLINE_VAR constexpr bool is_rvalue_reference_v = false; // determine whether type argument is an rvalue reference

template 
_INLINE_VAR constexpr bool is_rvalue_reference_v<_Ty&&> = true;

template 
struct is_rvalue_reference : bool_constant> {};

template 
_INLINE_VAR constexpr bool is_reference_v = false; // determine whether type argument is a reference

template 
_INLINE_VAR constexpr bool is_reference_v<_Ty&> = true;

template 
_INLINE_VAR constexpr bool is_reference_v<_Ty&&> = true;

template 
struct is_reference : bool_constant> {};
7.is_pointer: 是否是指针类型

都是利用特化变量,判断是否是指针类型。is开头的实现都差不多。

template 
_INLINE_VAR constexpr bool is_pointer_v = false; // determine whether _Ty is a pointer

template 
_INLINE_VAR constexpr bool is_pointer_v<_Ty*> = true;

template 
_INLINE_VAR constexpr bool is_pointer_v<_Ty* const> = true;

template 
_INLINE_VAR constexpr bool is_pointer_v<_Ty* volatile> = true;

template 
_INLINE_VAR constexpr bool is_pointer_v<_Ty* const volatile> = true;

template 
struct is_pointer : bool_constant> {};

需要注意为很么需要单独_Ty* const,因为又函数是const的,而模板匹配const int * 和int * const显然不是同一个概念。
demo

#include 
using namespace std;

template 
 constexpr bool is_pointers = false; // determine whether _Ty is a pointer

template 
constexpr bool is_pointers<_Ty*> = true;

int main()
{
    auto a = is_pointers;
    auto b = is_pointers;
    return 0;
}

8.is_null_pointer: 判断指针是否是空,利用is_same
template 
_INLINE_VAR constexpr bool is_null_pointer_v =
    is_same_v, nullptr_t>; // determine whether _Ty is cv-qualified nullptr_t
//remove_cv_t<_Ty>移除掉const,volatile属性
//利用is_same判断remove_cv_t<_Ty和nullptr_t是不是一个类型,是则为ture,不是则为false.
template 
struct is_null_pointer : bool_constant> {};
//继承bool_constant最后为true_type, false_type;
9.判断是否是基本类型(整形,浮点数,void,nullptr)
template 
_INLINE_VAR constexpr bool is_fundamental_v = is_arithmetic_v<_Ty> || is_void_v<_Ty> || is_null_pointer_v<_Ty>;
//is_arithmetic_v判断是不是算数类型,利用模板继承+is_same可变参数,一次提取比较,
//is_void_v判断是不是void类型
//is_null_pointer_v判断是不是空指针。
//is_arithmetic_v, is_void_v具体见其他文章。有介绍。
template 
struct is_fundamental : bool_constant> {}; // determine whether _Ty is a fundamental type
10.is_union:判断是不是内联结构,is_class:判断是不是类对象。is_convertible:判断能否转化从from到to。is_enum:判断是不是枚举类型(只能看到定义。没有找到具体实现。待日后找到后补上)
template 
struct is_union : bool_constant<__is_union(_Ty)> {}; // determine whether _Ty is a union

template 
_INLINE_VAR constexpr bool is_union_v = __is_union(_Ty);

template 
struct is_class : bool_constant<__is_class(_Ty)> {}; // determine whether _Ty is a class

template 
_INLINE_VAR constexpr bool is_class_v = __is_class(_Ty);

emplate 
struct is_convertible : bool_constant<__is_convertible_to(_From, _To)> {
    // determine whether _From is convertible to _To
};

template 
_INLINE_VAR constexpr bool is_convertible_v = __is_convertible_to(_From, _To);

template 
struct is_enum : bool_constant<__is_enum(_Ty)> {}; // determine whether _Ty is an enumerated type

template 
_INLINE_VAR constexpr bool is_enum_v = __is_enum(_Ty);
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/738822.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号