最終更新日時:
が更新

履歴 編集

function
<locale>

std::num_get::do_get

protected:
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, bool& val) const;               // (1) C++98
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, long& val) const;               // (2) C++98
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, long long& val) const;          // (3) C++11
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, unsigned short& val) const;     // (4) C++98
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, unsigned int& val) const;       // (5) C++98
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, unsigned long& val) const;      // (6) C++98
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, unsigned long long& val) const; // (7) C++11
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, float& val) const;              // (8) C++98
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, double& val) const;             // (9) C++98
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, long double& val) const;        // (10) C++98
  virtual iter_type do_get(iter_type in, iter_type end, ios_base& str,
                           ios_base::iostate& err, void*& val) const;              // (11) C++98

概要

入力イテレータ範囲[in, end)から文字列を読み取り、valの型に応じた数値・真偽値・ポインタへ変換する。get()から呼び出される、実際の解析を行う仮想関数である。

  • (1) : boolへ変換する
  • (2), (3) : 符号付き整数型 (long, long long) へ変換する
  • (4), (5), (6), (7) : 符号なし整数型 (unsigned short, unsigned int, unsigned long, unsigned long long) へ変換する
  • (8), (9), (10) : 浮動小数点数型 (float, double, long double) へ変換する
  • (11) : ポインタ (void*) へ変換する

効果

(2)〜(11)は、入力を数値へ変換する。変換は以下の3段階(Stage 1〜3)で行われる。(1)のbool版は、これらとは別に後述の規則で処理される。

Stage 1 : 変換指定の決定

str.flags()からbasefielduppercaseboolalphaを取り出し、変換指定(および必要な長さ修飾子)を決定する。

  • (2), (3), (4), (5), (6), (7) : 以下の表の条件を上から順に評価し、最初に真となった行の変換指定を使用する

    状態 stdioの変換指定に相当
    basefield ==ios_base::oct %o
    basefield ==ios_base::hex %X
    basefield == 0 %i
    符号付き整数型 %d
    符号なし整数型 %u
  • (8), (9), (10) : %g

  • (11) : %p

Stage 2 : 文字の抽出

[in, end)から、変換指定に合致する文字を順次抽出する。str.getloc()から取得したnumpunctファセットにより、numpunct::grouping()が空でない場合は桁区切り文字(numpunct::thousands_sep())を取り除き、小数点文字(numpunct::decimal_point())は'.'に置き換える。

Stage 3 : 数値への変換と格納

Stage 2で蓄積した文字列(フィールド)を、<cstdlib>で宣言される以下の関数の規則に従って数値へ変換する。

オーバーロード 対象の型 変換規則
(2), (3) 符号付き整数型 std::strtoll
(4), (5), (6), (7) 符号なし整数型 std::strtoull
(8) float std::strtof
(9) double std::strtod
(10) long double std::strtold
(11) void* 規定されていない

格納される値は以下のいずれかであり、いずれの場合も結果はvalへ格納される。

  • (2)〜(11) : 変換関数がフィールド全体を変換しなかった場合、0
  • (2), (3) : valに表現できないほど大きな正(負)の値を表す場合、表現可能な最大(最小)の値
  • (4), (5), (6), (7) : valに表現できない値を表す場合、表現可能な最大の値
  • (2)〜(11) : それ以外の場合、変換された値

変換関数がフィールド全体を変換しなかった場合、または表現可能な範囲外の値を表す場合、errstd::ios_base::failbitが設定される。

桁区切りの検査

(2)〜(10)では、取り除いた桁区切り文字の位置がnumpunct::grouping()と整合しているかが検査される。整合していない場合、errstd::ios_base::failbitが設定される。

入力終端の扱い

いずれの場合も、Stage 2の処理がin == endの判定によって終了した場合は、err |=std::ios_base::eofbitが行われる。

(1) bool版の処理

  • (str.flags()&std::ios_base::boolalpha) == 0の場合 : longと同様に入力を読み取り、格納しようとする値が0ならfalse1ならtrueを格納する。それ以外の場合はtrueを格納し、errstd::ios_base::failbitを設定する
  • そうでない場合 : numpunct::truename()numpunct::falsename()を対象列として、一意に定まるまで文字を照合する。一意にマッチした場合は対応する値をvalへ格納する。そうでない場合はfalseを格納し、errstd::ios_base::failbitを設定する

戻り値

  • (1) : 照合に使用しなかった最初の文字を指すイテレータ
  • (2)〜(11) : Stage 2で抽出を終えた位置、すなわち変換に使用しなかった最初の文字を指すイテレータ

バージョン

言語

  • C++98

関連項目

参照

  • LWG Issue 1169. num_get not fully compatible with strto*
    • C++17で、floatstd::strtoflong doublestd::strtoldを使用することが明示され(std::strtoll/std::strtoull/std::strtodは変更なし)、符号なし整数型で表現できない値に対しては(正負によらず)常に表現可能な最大の値を格納する形に整理された。これによりC標準ライブラリと整合するようになった