我是靠谱客的博主 魁梧果汁,最近开发中收集的这篇文章主要介绍type_traits之 析取 && 合取 && 否定前言析取,disjunction合取,conjunction否定,negation,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

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

前言

  • C++17完善了< type_traits>,增加了3个有趣的traits。分别为析取traits,合取traits,否定traits,实现的方法有很多种,我使用VS2019的源码来写这篇博客。
  • VS中标识符的命名风格非常统一。如果标识符的名字是下划线加上大写字母开头,那么代表这个标识符是内部使用,不会暴露给用户。
  • 首先,先做一下预备工作。介绍一下模板元编程的基本工具——integral_constant
template <class T, T _Val>
struct integral_constant{
static constexpr T value = _Val;
// ...
};
  • 上面是integral_constant的部分源码,虽然完整的源码不算太长,但是与我要讨论的无关,(而且我认为不太重要),可以看到该模板元函数仅仅是定义了一个关于类型T的编译期常量。

bool_constant:

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

template <bool _Val>
using bool_constant = integral_constant<bool, _Val>;
using true_type
= bool_constant<true>;
//has value true
using false_type = bool_constant<false>;
//has value false
  • bool_constant是一个bool常量,而对于bool常量,只有两种情况,这两种情况也很常见,我们也为其写了捷径,即true_type,相当于integral_constant<bool, true >。false_type,相当于integral_constant<bool, false >。

析取,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 <bool _First_value, class _First, class..._Rest>
struct _Disjunction {
using type = _First; //_First_value为true,或者所有类型都为true时,返回_First。
};
template <class _First, class _Next, class..._Rest>
struct _Disjunction<false, _First, _Next, _Rest...> {
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下一个。
/*
VS 2019的源码
*/
template <class..._Traits>
struct disjunction : false_type {}; //如果_Traits为空,那么返回false;
template <class _First, class..._Rest>
//虽然type是一种类型,但是C++规定此处不需要typename关键字;
struct disjunction<_First, _Rest...> : _Disjunction<_First::value, _First, _Rest...>::type {};
//错误写法,该写法是声明了一种type,而继承type是声明了一个value常量。
/* template <class _First, class..._Rest>
struct disjunction<_First, _Rest...>{
using type = typename _Disjunction<_First::value, _First, _Rest...>::type;
}; */
  • 如果_Traits为空,那么就返回false。如果_Traits参数包至少拥有一种类型,那么就继承_Disjunction的type。注意,是继承的type,而非使用using表达式。
  • 如果_Traits为空,那么主模板默认为false。
  • 在模板特化中,disjunction继承_Disjunction的type。
  • 而一旦某个traits为true,_Disjunction就会截断,直接返回type给disjunction,这也符合我们普通析取表达式的特性。

_v后缀:

  • C++为返回value的模板元函数提供了调用的捷径。
template <class..._Traits>
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 <bool _First_value, class _First, class..._Rest>
struct _Conjunction {
using type = _First;
};
template <class _First, class _Next, class..._Rest>
struct _Conjunction<true, _First, _Next, _Rest...> { //_Next如果不存在,触发SFINAE
using type = typename _Conjunction<_Next::value, _Next, _Rest...>::type;
};
  • 主模板默认为_First的类型。
  • 特化模板中,如果第一个类型的value为true,那么递归traits下一个。一旦有一个false,直接截断。

conjunction:

template <class..._Traits>
struct conjunction : true_type {};
template <class _First, class..._Rest>
struct conjunction<_First, _Rest...> : _Conjunction<_First::value, _First, _Rest...>::type {};
  • 主模板默认为true。
  • 特化模板中,继承_Conjunction的type。
  • 类似的,conjunction也有shortcut。
template <class..._Traits>
inline constexpr bool conjunction_v = conjunction<_Traits...>::value;

否定,negation

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

template <class _Ty>
struct negative : bool_constant<!static_cast<bool>(_Ty::value)> {};
  • negative继承了bool_constant。
  • bool_constant则定义了一个常量,为_Ty::value的否定。为了保证是bool类型的,所以使用了类型转换。

最后

以上就是魁梧果汁为你收集整理的type_traits之 析取 && 合取 && 否定前言析取,disjunction合取,conjunction否定,negation的全部内容,希望文章能够帮你解决type_traits之 析取 && 合取 && 否定前言析取,disjunction合取,conjunction否定,negation所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部