8

With my recent upgrade to Mac OS X 10.9 the default standard C++ library changed from libstdc++ to libc++. Since then I observe unexpected behaviour of the stringstream operator>>(double) documented in the code example below.

In summary the libc++ seems to have problems with extracting double values from stringstreams when the double value is followed by a letter.

I already checked the standard (2003) but I can't find any specific information if extraction should work in this case or not.

So I would be grateful for any input whether this is a bug in libc++ or libstdc++.

#include <sstream>
#include <iostream>

using namespace std;

void extract_double(const string & s)
{
  stringstream ss;
  double d;

  ss << s;
  ss >> d;
  if(!ss.fail())
    cout << "'" << ss.str() << "' converted to " << d << endl;
  else
    cout << "'" << ss.str() << "' failed to convert to double" << endl;
}

int main()
{
  extract_double("-4.9");
  extract_double("-4.9 X");
  extract_double("-4.9_");
  extract_double("-4.9d");
  extract_double("-4.9X");
}

Compiling the code with c++ --stdlib=libc++ streamtest.cxx gives

'-4.9' converted to -4.9
'-4.9 X' converted to -4.9
'-4.9_' converted to -4.9
'-4.9d' failed to convert to double
'-4.9X' failed to convert to double

Compiling the code with c++ --stdlib=libstdc++ streamtest.cxx gives

'-4.9' converted to -4.9
'-4.9 X' converted to -4.9
'-4.9_' converted to -4.9
'-4.9d' converted to -4.9
'-4.9X' converted to -4.9

Compiler version is

$ c++ --version
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix
Stephan Aiche
  • 81
  • 1
  • 3

1 Answers1

2

It looks like that libstdc++ is right and libc++ is wrong, according to the 22.4.2.1.2 of the (2011) standard.

At stage 2,

If it [the character - n.m.] is not discarded, then a check is made to determine if c is allowed as the next character of an input field of the conversion specifier returned by Stage 1 ["%g" in this case - n.m.] . If so, it is accumulated.

Since %g conversion specifier does not admit d or X characters, the character is not accumulated. It is not discarded either (only group separator characters can be discarded). Therefore Stage 2 must end at this point.

Then at stage 3 accumulated characters are converted.

It looks like libc++ erroneously accumulates d and X at stage 2, then attempts to convert them, and this fails.

n. 'pronouns' m.
  • 95,181
  • 13
  • 111
  • 206
  • I reported the problem to the libc++ guys. See bug [17782](http://llvm.org/bugs/show_bug.cgi?id=17782) – Stephan Aiche Nov 02 '13 at 08:40
  • Appears only to happen if the trailing character is 'A' .. 'F', 'I', 'N', 'P' and 'X' (and the same characters in lower case) – Marshall Clow Nov 04 '13 at 15:16
  • @MarshallClow: OK, A to F and X can appear in hexadecimal numbers, and they actually appear in the relevant portion of the standard, so one could probably see where things went wrong if those were the only culprits. But how I, N and P came into play? – n. 'pronouns' m. Nov 04 '13 at 15:29
  • In hexadecimal floats, you can't use 'E' for the exponent - that's a digit. The standard says to use 'P' instead. Libc++ will also parse "inf" and "nan", so that's where the 'I' and 'N' come from. However, in your example, it's clearly doing it incorrectly. – Marshall Clow Nov 04 '13 at 16:48
  • @MarshallClow: hm, if hex floats are allowed, then it seems libc++ **is** correct! Where does the standard talk about them? And if P is allowed, why it's not mentioned in 22.4.2.1.2? – n. 'pronouns' m. Nov 04 '13 at 17:01
  • You have to go back to C99 (which the C++ standard incorporates by reference). Section 6.4.4.2 Floating constants – Marshall Clow Nov 04 '13 at 18:56
  • @MarshallClow: aha, I see. The relevant section is in fact 7.20.1.3 (talking about strtod). C99 strtod also accepts NAN and INF (and also INFINITY, so the set should contain T and Y!) But then 22.4.2.1.2 (of C++11) should have mentioned all these letters too. – n. 'pronouns' m. Nov 04 '13 at 19:30
  • @MarshallClow: OTOH the standard says "allowed as the *next* character of an input field"... hm, looks like libc++ is wrong after all. – n. 'pronouns' m. Nov 04 '13 at 19:46