C++ type traits分析

admin 2025年1月13日10:44:32评论5 views字数 6207阅读20分41秒阅读模式
来源:xdesk
https://blog.csdn.net/xiangbaohui/article/details/106571580

C++ type traits分析

我们在平时常常会听到有人说traits/萃取等高大上的东西,有时候可能也会对此产生很大的疑问,觉得type tratis很高大上,高深莫测;其实说到底这个东西很简单,总结为一句话就是在运行的时候识别类型(即类型萃取)。

本文我们大致看一下type traits的基本实现技术。

1. integral_constant

了解萃取机之前,我们先了解一下integral_constant, 这个在C++库中定义为一个常量的整数,定义如下:

template<class _Ty,  _Ty _Val>  struct integral_constant  {  // convenient template for integral constant types  static constexpr _Ty value = _Val;  using value_type = _Ty;  using type = integral_constant;  constexpr operator value_type() const noexcept{  // return stored value    return (value);    }  _NODISCARD constexpr value_type operator()() const noexcept{  // return stored value    return (value);    }  };

这个的主要核心是定义了一个静态常量值:

static constexpr _Ty value = _Val;

为什么需要定义这样一个东西呢?我们不直接使用_Ty value = _Val定义一个全局的变量不是挺好的嘛,为啥需要搞的那么麻烦呢?

主要原因是:为了C++编译的时候能够使用模板初编译来确定其中的值。

从integral_constant引申出来了两个东西:

true_type

false_type

这两个东西分别代表TRUE 和 FALSE,如下:

template<bool _Val>  using bool_constant = integral_constant<bool, _Val>;using true_type = bool_constant<true>;using false_type = bool_constant<false>;

2. C++库的type traits

2.1 Primary type categories

C++ type traits分析

2.2 Composite type categories

C++ type traits分析

2.3 Type properties

C++ type traits分析

2.4 Type features

C++ type traits分析

2.5 Type relationships

C++ type traits分析

2.6 Property queries

C++ type traits分析

2.7 Type transformations

C++ type traits分析

3. type traits的例子

class CData1{public:  CData1() {}  virtual ~CData1() {}};class CData2{public:  CData2() {}  ~CData2() {}};class CData3{public:  int a;  int b;  int c;};int main(int args, char* argv[]){  std::cout << "CData1 has_virtual_destructor : " << std::has_virtual_destructor::value << std::endl;  std::cout << "CData2 has_virtual_destructor : " << std::has_virtual_destructor::value << std::endl;  std::cout << "CData3 has_virtual_destructor : " << std::has_virtual_destructor::value << std::endl;  std::cout << "CData1 is_pod : " << std::is_pod::value << std::endl;  std::cout << "CData2 is_pod : " << std::is_pod::value << std::endl;  std::cout << "CData3 is_pod : " << std::is_pod::value << std::endl;  return 0;}

输出结果如下:

CData1 has_virtual_destructor : 1CData2 has_virtual_destructor : 0CData3 has_virtual_destructor : 0CData1 is_pod : 0CData2 is_pod : 0CData3 is_pod : 1

从上面我们可以看到type traits是非常厉害的,他能够在编译器的时候知道C++定义类型的所有属性。

4. type tratis的实现

我们看几个例子来大致看一下type traits的实现原理.

4.1 std::is_integral

std::is_integral用来判断一个类型是否是整数,这个的实现原理如下:

// STRUCT TEMPLATE _Is_integraltemplate<class _Ty>  struct _Is_integral    : false_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  }; #ifdef _NATIVE_WCHAR_T_DEFINEDtemplate<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  }; #endif /* _NATIVE_WCHAR_T_DEFINED */template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };  // STRUCT TEMPLATE is_integraltemplate<class _Ty>  struct is_integral    : _Is_integral<remove_cv_t<_Ty>>::type  {  // determine whether _Ty is integral  };

首先定义了一个template struct _Is_integral : false_type 通用的模板,这个模板中有一个bool value = false的静态成员。

然后就是真的所有的整数类型,创建特化模块,例如如下:

template<>  struct _Is_integral    : true_type  {  // determine whether _Ty is integral  };

这个模板中有一个bool value = true的静态成员。

从这里大致我们可以看出type traits是使用特化来确定特定的情况。

4.2 std::is_pod

对于简单类型的判断比较容易,我们实现所有类型的模板特化即可,但是对于类复杂类型的判断,就比较麻烦了,C++标准库的实现如下:

template<class _Ty>  struct is_pod    : bool_constant<__is_pod(_Ty)>  {  // determine whether _Ty is a POD type  };template<class _Ty>  _INLINE_VAR constexpr bool is_pod_v = __is_pod(_Ty);  // STRUCT TEMPLATE is_emptytemplate<class _Ty>  struct is_empty    : bool_constant<__is_empty(_Ty)>  {  // determine whether _Ty is an empty class  };template<class _Ty>  _INLINE_VAR constexpr bool is_empty_v = __is_empty(_Ty);  // STRUCT TEMPLATE is_polymorphictemplate<class _Ty>  struct is_polymorphic    : bool_constant<__is_polymorphic(_Ty)>  {  // determine whether _Ty is a polymorphic type  };

对于__is_podC++标准库并没有公开的代码,这里也不知道具体如何实现,跟编译器的底层实现细节有关,但是从我们所有的type traits来说,这个功能还是十分强大的。

5. iterator_traits

在萃取中,存在一个比较重要的萃取,如果上面的is_class, is_pod都没有用过的话,那么iterator_traits这个萃取机肯定是用过的,例如:

  template<typename _InputIterator, typename _Size, typename _ForwardIterator>    inline _ForwardIterator    uninitialized_copy_n(_InputIterator __first, _Size __n,                         _ForwardIterator __result){ return std::__uninitialized_copy_n(__first, __n, __result,                                         std::__iterator_category(__first)); }

其中std::__iterator_category(__first))这个就是类型萃取机,这个实现如下:

 template<typename _Iter>    inline _GLIBCXX_CONSTEXPR    typename iterator_traits<_Iter>::iterator_category    __iterator_category(const _Iter&)    { return typename iterator_traits<_Iter>::iterator_category(); }

iterator_traits 这个就是迭代器的萃取机,这个萃取机可以做如下事情:

  • 萃取迭代器的类型。

  • 萃取迭代器代表的值的类型。

  • 萃取迭代器使用值的引用指针等类型。

这个迭代器实现如下:

 template<typename _Iterator>    struct iterator_traits    {      typedef typename _Iterator::iterator_category iterator_category;      typedef typename _Iterator::value_type        value_type;      typedef typename _Iterator::difference_type   difference_type;      typedef typename _Iterator::pointer           pointer;      typedef typename _Iterator::reference         reference;    };  /// Partial specialization for pointer types.  template<typename _Tp>    struct iterator_traits<_Tp*>    {      typedef random_access_iterator_tag iterator_category;      typedef _Tp                         value_type;      typedef ptrdiff_t                   difference_type;      typedef _Tp*                        pointer;      typedef _Tp&                        reference;    };  /// Partial specialization for const pointer types.  template<typename _Tp>    struct iterator_traits    {      typedef random_access_iterator_tag iterator_category;      typedef _Tp                         value_type;      typedef ptrdiff_t                   difference_type;      typedef const _Tp*                  pointer;      typedef ptrdiff_t                   difference_type;      typedef const _Tp*                  pointer;      typedef const _Tp&                  reference;    };

对于我们STL的迭代器,都需要定义这些类型:

  • Iterator::iterator_category 迭代器类型。

  • Iterator::value_type : 迭代器的值类型。

  • Iterator::difference_type : 迭代器的距离信息。

  • Iterator::pointer :迭代器指针。

  • Iterator::reference : 迭代器的引用。

STL的迭代器其实就是模拟指针来实现的,所以指针,应该天生适合最合适的迭代器,因此给_Tp* 和 const _Tp* 定义了特殊的萃取类型。

6. 总结

从上面分析,对于C++库,萃取的实现一般都是定义模板来实现,对于普通的类型,匹配这个模板的定义;然后针对特殊类型实现特化模板支持。

原文始发于微信公众号(汇编语言):C++ type traits分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月13日10:44:32
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   C++ type traits分析https://cn-sec.com/archives/1106192.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息