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

type

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

type

目录

前言析取,disjunction合取,conjunction否定,negation

前言

C++17完善了< type_traits>,增加了3个有趣的traits。分别为析取traits,合取traits,否定traits,实现的方法有很多种,我使用VS2019的源码来写这篇博客。VS中标识符的命名风格非常统一。如果标识符的名字是下划线加上大写字母开头,那么代表这个标识符是内部使用,不会暴露给用户。首先,先做一下预备工作。介绍一下模板元编程的基本工具——integral_constant。

template 
struct integral_constant{
	static constexpr T value = _Val;
	// ...
};

上面是integral_constant的部分源码,虽然完整的源码不算太长,但是与我要讨论的无关,(而且我认为不太重要),可以看到该模板元函数仅仅是定义了一个关于类型T的编译期常量。

bool_constant:

在所有类型的常量中,我们常常会用到关于bool类型的常量,即integral_constant< bool, _Val >,所以我们就有了对bool常量的捷径。

template 
using bool_constant = integral_constant;

using true_type  = bool_constant;   //has value true
using false_type = bool_constant;  //has value false

bool_constant是一个bool常量,而对于bool常量,只有两种情况,这两种情况也很常见,我们也为其写了捷径,即true_type,相当于integral_constant。false_type,相当于integral_constant。 析取,disjunction

考虑普通的析取表达式,即一系列的条件表达式的逻辑或,像下面这样

//普通的析取表达式
condition1 || condition2 || conditon3 || ...
1 || 2 || 3 || 4;

int a = 0, b = 1, c= 2;
a < b || b < c || c < a;

而逻辑或拥有的特性便是:从左向右判断,如果有一个条件表达式为真,那么就直接截断,返回true。返回false的条件是所有的条件表达式都是false。而作为模板元函数的析取,操纵的“条件表达式”为一系列类型。disjunction获得一系列的类型,从左向右去萃取每种类型的value(这就必须保证每种类型都会返回一个常量value),如果发现value为true,那么直接返回true。否则,返回false。特殊考虑: 如果没有传入类型,C++规定,disjunction默认为false。

辅助traits: _Disjunction

// 该traits仅仅在VS2019内部使用,用于实现disjunction的辅助traits。
template 
struct _Disjunction {    
	using type = _First; //_First_value为true,或者所有类型都为true时,返回_First。
};   

template 
struct _Disjunction {
	using type = typename _Disjunction<_Next::value, _Next, _Rest...>::type;
}; //如果第一种类型为false,那么递归去trait下一种类型

_Disjunction以下划线加上大写字母开头,表示用于内部实现,是一个辅助traits。主模板中,默认返回first的类型。在模板特化中,必须保证first::value为false,且传递过来至少两种类型。如果first::value为true,那么调用主模板;如果只传递过来一种类型,_Next就不存在,就会触发SFINAE,调用主模板。模板特化traits第一个类型的value为false,那么递归trait下一个。

template 
struct disjunction : false_type {}; //如果_Traits为空,那么返回false;

template   //虽然type是一种类型,但是C++规定此处不需要typename关键字;
struct disjunction<_First, _Rest...> : _Disjunction<_First::value, _First, _Rest...>::type {};

//错误写法,该写法是声明了一种type,而继承type是声明了一个value常量。

如果_Traits为空,那么就返回false。如果_Traits参数包至少拥有一种类型,那么就继承_Disjunction的type。注意,是继承的type,而非使用using表达式。如果_Traits为空,那么主模板默认为false。在模板特化中,disjunction继承_Disjunction的type。而一旦某个traits为true,_Disjunction就会截断,直接返回type给disjunction,这也符合我们普通析取表达式的特性。

_v后缀:

C++为返回value的模板元函数提供了调用的捷径。

template 
inline constexpr bool disjunction_v = disjunction<_Traits...>::value;
合取,conjunction

合取与析取类似,即使用逻辑与连接一系列的条件表达式。

condition1 && condition2 && condition3 && ...
1 && 2 && 3 && 4;

int a = 0, b = 1, c = 2;
a < b && b < c && c < a;

合取的特性为:如果是空,那么默认为true。从左向右匹配,如果某个value为false,那么直接截断,返回false。与disjunction完全类似,我们也有一个辅助traits。

辅助traits: _Conjunction

template 
struct _Conjunction {
	using type = _First; 
};

template 
struct _Conjunction { //_Next如果不存在,触发SFINAE
	using type = typename _Conjunction<_Next::value, _Next, _Rest...>::type;
};

主模板默认为_First的类型。特化模板中,如果第一个类型的value为true,那么递归traits下一个。一旦有一个false,直接截断。

conjunction:

template 
struct conjunction : true_type {};

template 
struct conjunction<_First, _Rest...> : _Conjunction<_First::value, _First, _Rest...>::type {};

主模板默认为true。特化模板中,继承_Conjunction的type。类似的,conjunction也有shortcut。

template 
inline constexpr bool conjunction_v = conjunction<_Traits...>::value;
否定,negation

否定极为简单,就是取反即可。

template 
struct negative : bool_constant(_Ty::value)> {};

negative继承了bool_constant。bool_constant则定义了一个常量,为_Ty::value的否定。为了保证是bool类型的,所以使用了类型转换。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/738537.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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