This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of TC1 status.

### 17. Bad bool parsing

Section: 30.4.3.2.3 [facet.num.get.virtuals] Status: TC1 Submitter: Nathan Myers Opened: 1998-08-06 Last modified: 2016-08-09

Priority: Not Prioritized

View other active issues in [facet.num.get.virtuals].

View all other issues in [facet.num.get.virtuals].

View all issues with TC1 status.

Discussion:

This section describes the process of parsing a text boolean value from the input stream. It does not say it recognizes either of the sequences "true" or "false" and returns the corresponding bool value; instead, it says it recognizes only one of those sequences, and chooses which according to the received value of a reference argument intended for returning the result, and reports an error if the other sequence is found. (!) Furthermore, it claims to get the names from the ctype<> facet rather than the numpunct<> facet, and it examines the "boolalpha" flag wrongly; it doesn't define the value "loc"; and finally, it computes wrongly whether to use numeric or "alpha" parsing.
I believe the correct algorithm is "as if":

      // in, err, val, and str are arguments.
      err = 0;
      const numpunct<charT>& np = use_facet<numpunct<charT> >(str.getloc());
      const string_type t = np.truename(), f = np.falsename();
      bool tm = true, fm = true;
      size_t pos = 0;
      while (tm && pos < t.size() || fm && pos < f.size()) {
        if (in == end) { err = str.eofbit; }
        bool matched = false;
        if (tm && pos < t.size()) {
          if (!err && t[pos] == *in) matched = true;
          else tm = false;
        }
        if (fm && pos < f.size()) {
          if (!err && f[pos] == *in) matched = true;
          else fm = false;
        }
        if (matched) { ++in; ++pos; }
        if (pos > t.size()) tm = false;
        if (pos > f.size()) fm = false;
      }
      if (tm == fm || pos == 0) { err |= str.failbit; }
      else                      { val = tm; }
      return in;

Notice this works reasonably when the candidate strings are both empty, or equal, or when one is a substring of the other. The proposed text below captures the logic of the code above.

Proposed resolution:

In 30.4.3.2.3 [facet.num.get.virtuals], in the first line of paragraph 14, change "&&" to "&".

Then, replace paragraphs 15 and 16 as follows:

> Otherwise target sequences are determined "as if" by calling the members `falsename()` and `truename()` of the facet obtained by `use_facet<numpunct<charT> >(str.getloc())`. Successive characters in the range `[in,end)` (see [lib.sequence.reqmts]) are obtained and matched against corresponding positions in the target sequences only as necessary to identify a unique match. The input iterator `in` is compared to `end` only when necessary to obtain a character. If and only if a target sequence is uniquely matched, `val` is set to the corresponding value.

> The `in` iterator is always left pointing one position beyond the last character successfully matched. If `val` is set, then err is set to `str.goodbit`; or to `str.eofbit` if, when seeking another character to match, it is found that `(in==end)`. If `val` is not set, then err is set to `str.failbit`; or to `(str.failbit|str.eofbit)`if the reason for the failure was that `(in==end)`. [Example: for targets `true`:"a" and `false`:"abb", the input sequence "a" yields `val==true` and `err==str.eofbit`; the input sequence "abc" yields `err=str.failbit`, with `in` ending at the 'c' element. For targets `true`:"1" and `false`:"0", the input sequence "1" yields `val==true` and `err=str.goodbit`. For empty targets (""), any input sequence yields `err==str.failbit`. --end example]