最終更新日時(UTC):
が更新

履歴 編集

class template
<string>

std::char_traits

namespace std {
  template<class charT> struct char_traits;

  template<> struct char_traits<char>;
  template<> struct char_traits<char8_t>;  // C++20から
  template<> struct char_traits<char16_t>; // C++11から
  template<> struct char_traits<char32_t>; // C++11から
  template<> struct char_traits<wchar_t>;
}

概要

char_traitsは、basic_string文字列クラスのおける、各要素の特性を使用するためのクラスである。
このクラスと同じインタフェースのクラスを用意してbasic_stringクラスのテンプレート引数として指定することにより、ユーザー独自の処理に切り替えることが可能である。たとえば、大文字・小文字を区別しない比較のためのカスタマイズに利用できる。

テンプレートパラメータは以下を意味する:

  • charT : basic_stringクラスが扱う文字型

静的メンバ関数

名前 説明 対応バージョン
assign 代入
eq 等値比較
lt 小なり比較
compare 比較
length 文字列長を取得する
find 文字列中から特定の値を検索する
move 文字列を他のシーケンスにコピーする
copy 文字列を他のシーケンスにコピーする
not_eof 文字がファイル終端文字(EOF)じゃないかを判定する
to_char_type 数値を文字に変換する
to_int_type 文字を数値に変換する
eq_int_type 数値の等値比較
eof ファイル終端文字(EOF)を表す数値を取得する

メンバ型

名前 説明 対応バージョン
char_type 文字コンテナの実装で使用される文字型
int_type 文字に対応する値を表す数値型
off_type 文字の差を表す型
pos_type 位置を表す型
state_type ストリームのマルチバイト文字の変換の状態を表す型

charによる特殊化のメンバ型定義

名前 説明 対応バージョン
char_type char
int_type int
off_type streamoff
pos_type streampos
state_type mbstate_t

char8_tによる特殊化のメンバ型定義 (C++20)

名前 説明 対応バージョン
char_type char8_t C++20
int_type unsigned int C++20
off_type streamoff C++20
pos_type u8streampos C++20
state_type mbstate_t C++20

char16_tによる特殊化のメンバ型定義 (C++11)

名前 説明 対応バージョン
char_type char16_t C++11
int_type uint_least16_t C++11
off_type streamoff C++11
pos_type u16streampos C++11
state_type mbstate_t C++11

char32_tによる特殊化のメンバ型定義 (C++11)

名前 説明 対応バージョン
char_type char32_t C++11
int_type uint_least32_t C++11
off_type streamoff C++11
pos_type u32streampos C++11
state_type mbstate_t C++11

wchar_tによる特殊化のメンバ型定義

名前 説明 対応バージョン
char_type wchar_t
int_type wint_t
off_type streamoff
pos_type wstreampos
state_type mbstate_t

基本的な使い方

#include <iostream>
#include <string>

int main()
{
  // std::stringと同じ
  std::basic_string<char, std::char_traits<char>> a = "aaa";
  std::basic_string<char, std::char_traits<char>> b = "bbb";

  // char_traits::compare()で比較が行われる
  if (a < b) {
    std::cout << "then" << std::endl;
  }
  else {
    std::cout << "else" << std::endl;
  }
}

出力

then

大文字・小文字を区別しない文字列比較をするbasic_stringを定義 (C++20)

#include <string>
#include <compare>
#include <cctype>
#include <algorithm>

template <class T>
class case_insensitive_char_traits {
  using base_traits = std::char_traits<T>;
public:
  using char_type = char;
  using int_type = int;
  using off_type = std::streamoff;
  using pos_type = std::streampos;
  using state_type = std::mbstate_t;
  using comparison_category = std::weak_ordering;

  static constexpr void assign(char_type& c1, const char_type& c2) noexcept {
    base_traits::assign(c1, c2);
  }

  static constexpr bool eq(char_type c1, char_type c2) noexcept {
    return base_traits::eq(std::tolower(c1), std::tolower(c2));
  }

  static constexpr bool lt(char_type c1, char_type c2) noexcept {
    return base_traits::lt(std::tolower(c1), std::tolower(c2));
  }

  static constexpr int compare(const char_type* s1, const char_type* s2, size_t n) {
    auto order = std::lexicographical_compare_three_way(s1, s1 + n, s2, s2 + n,
           [](char_type c1, char_type c2) -> std::weak_ordering {
             return std::tolower(c1) <=> std::tolower(c2);
           });
    return order == std::weak_ordering::equivalent ? 0 :
           order == std::weak_ordering::greater ? 1 :
           -1;
  }

  static constexpr size_t length(const char_type* s) {
    return base_traits::length(s);
  }

  static constexpr const char_type* find(const char_type* s, size_t n,
                                         const char_type& a) {
    return std::find_if(s, s + n, [a](char_type c) {
      return std::tolower(c) == a;
    });
  }

  static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n) {
    return base_traits::move(s1, s2, n);
  }

  static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n) {
    return base_traits::copy(s1, s2, n);
  }

  static constexpr char_type* assign(char_type* s, size_t n, char_type a) {
    return base_traits::assign(s, n, a);
  }
};

#include <iostream>
int main() {
  using case_insensitive_string =
      std::basic_string<char, case_insensitive_char_traits<char>>;
  case_insensitive_string a = "AbC";
  case_insensitive_string b = "aBc";

  if (a == b) {
    std::cout << "equal" << std::endl;
  }
  else {
    std::cout << "not equal" << std::endl;
  }
}

出力

equal