STL 的 char_traits 分析

#-char_traits #-STL

类模板 __char_traits_base 用来作为 char_traits 的基类。

template <class _CharT, class _IntT> class __char_traits_base {

####类模板 __char_traits_base####

__char_traits_base 中定义了两个公有属性的成员类型。

public:
  typedef _CharT char_type;
  typedef _IntT int_type;

__char_traits_base 定义了一系列的成员函数,char_traits 中大量的成员函数都是继承自基类。

函数 assign 用 char_type 类型的给定变量 __c2 对另一个 char_type 类型的变量进行赋值。

  static void assign(char_type& __c1, const char_type& __c2) { __c1 = __c2; }

函数 eq 判断两个类型为 char_type 的变量是否相等。

  static bool eq(const _CharT& __c1, const _CharT& __c2) 
    { return __c1 == __c2; }

函数 lt 判断给定的 char_type 类型的变量 __c1 是否要小于另一个同类型的变量 __c2 。

  static bool lt(const _CharT& __c1, const _CharT& __c2) 
    { return __c1 < __c2; }

函数比较从 __s1 开始长度为 __n 的序列是否和从 __s2 开始长度为 __n 的序列大小,如果第一个序列小,则返回 -1,如果第一个序列大,则返回 1 。如果两个序列相等,则返回 0 。

  static int compare(const _CharT* __s1, const _CharT* __s2, size_t __n) {
    for (size_t __i = 0; __i < __n; ++__i)
      if (!eq(__s1[__i], __s2[__i]))
	return __s1[__i] < __s2[__i] ? -1 : 1;
    return 0;
  }

函数 length 计算从 __s 开始的序列的长度,函数声明一个 CharT 类型的空实例 __nullchar 。从 __s 开始往后遍历,如果碰到一个为 __nullchar 的元素,则停止遍历,并返回 __nullchar 之前的元素个数。

  static size_t length(const _CharT* __s) {
    const _CharT __nullchar = _CharT();
    size_t __i;
    for (__i = 0; !eq(__s[__i], __nullchar); ++__i)
      {}
    return __i;
  }

在从 __s 开始长度为 __n 的序列中查找值为 __c 的元素。

  static const _CharT* find(const _CharT* __s, size_t __n, const _CharT& __c)
  {
    for ( ; __n > 0 ; ++__s, --__n)
      if (eq(*__s, __c))
	return __s;
    return 0;
  }

函数 move 调用 memmove 将从 __s2 开始长度为 __n 的序列移动到 __s1 开始的位置。memmove 能保证当 __s2 和 __s1 之间有重叠时也能顺利移动。

  static _CharT* move(_CharT* __s1, const _CharT* __s2, size_t __n) {
    memmove(__s1, __s2, __n * sizeof(_CharT));
    return __s1;
  }

函数 copy 调用 memcpy 将从 __s2 开始长度为 __n 的序列复制到 __s1 开始的位置。当 __s1 和 __s2 之间有重叠时可能会产生覆盖的问题。

  static _CharT* copy(_CharT* __s1, const _CharT* __s2, size_t __n) {
    memcpy(__s1, __s2, __n * sizeof(_CharT));
    return __s1;
  } 

函数 assign 将 __s 开始长度为 __n 的序列中的元素都赋值为 __c 。

  static _CharT* assign(_CharT* __s, size_t __n, _CharT __c) {
    for (size_t __i = 0; __i < __n; ++__i)
      __s[__i] = __c;
    return __s;
  }

函数 not_eof 判断 __c 是否为 eof 。

  static int_type not_eof(const int_type& __c) {
    return !eq_int_type(__c, eof()) ? __c : 0;
  }

函数 to_char_type 将 int_type 类型的变量 __c 强制转换为 char_type 类型的变量,并将强制转换得到的变量作为返回值返回。

  static char_type to_char_type(const int_type& __c) {
    return static_cast<char_type>(__c);
  }

函数 to_int_type 将 char_type 类型的变量 __c 强制转换为 int_type 类型的变量,并将强制转换得到的变量作为返回值返回。

  static int_type to_int_type(const char_type& __c) {
    return static_cast<int_type>(__c);
  }

函数 eq_int_type 判断两个 int_type 类型的变量 __c1 和 __c2 是否相等。

  static bool eq_int_type(const int_type& __c1, const int_type& __c2) {
    return __c1 == __c2;
  }

函数 eof 用来返回 eof(即 -1)。

  static int_type eof() {
    return static_cast<int_type>(-1);
  }

####类模板 char_traits####

类模板 char_traits 继承自 __char_traits_base<_CharT, _CharT> 。

template <class _CharT> class char_traits
  : public __char_traits_base<_CharT, _CharT>
{};

当 char_traits 的模板实参为 char 时, char_traits 有如下的偏特化定义。该定义中重定义了 to_char_type, to_int_type, compare, length, assign 函数。

to_char_type 函数将 int 类型的变量强制转换为 char 类型,to_int_type 类型变量将 char 类型变量转换为 int 类型。 compare 调用 memcmp 比较两个字符串的大小。 length 函数调用 strlen 求给定字符串的长度。 assign 函数实现 const char 类型的变量对 char 类型变量的赋值,而第二个 assign 函数调用 memset 对从 __s 开始长度为 __n 的字符串中的字符赋同一个值。

__STL_TEMPLATE_NULL class char_traits<char> 
  : public __char_traits_base<char, int>
{
public:
  static char_type to_char_type(const int_type& __c) {
    return static_cast<char_type>(static_cast<unsigned char>(__c));
  }

  static int_type to_int_type(const char_type& __c) {
    return static_cast<unsigned char>(__c);
  }

  static int compare(const char* __s1, const char* __s2, size_t __n) 
    { return memcmp(__s1, __s2, __n); }
  
  static size_t length(const char* __s) { return strlen(__s); }

  static void assign(char& __c1, const char& __c2) { __c1 = __c2; }

  static char* assign(char* __s, size_t __n, char __c)
    { memset(__s, __c, __n); return __s; }
};

当char_traits 的模板实参为 wchar_t 时使用如下偏特化定义。

__STL_TEMPLATE_NULL class char_traits<wchar_t>
  : public __char_traits_base<wchar_t, wint_t>
{};