2013-11-01 2 views
8

С моим недавним обновлением до Mac OS X 10.9 стандартная библиотека C++ по умолчанию менялась с libstdC++ на libC++. С тех пор я наблюдаю неожиданное поведение оператора stringstream >> (double), задокументированного в примере кода ниже.Несоответствие между оператором istream >> (double & val) между libC++ и libstdC++

Таким образом, libC++, похоже, имеет проблемы с извлечением двойных значений из строковых потоков, когда за двойным значением следует буква.

Я уже проверил стандарт (2003), но я не могу найти никакой конкретной информации, если извлечения должно работать в этом случае или нет.

Поэтому я был бы благодарен за любой вклад, будь то ошибка в libC++ или 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"); 
} 

Компиляция кода с c++ --stdlib=libc++ streamtest.cxx дает

'-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 

Компиляция кода с c++ --stdlib=libstdc++ streamtest.cxx дает

'-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 версия

$ 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 
+0

Местный «C» в обоих случаях. –

ответ

2

Похоже, что libstdC++ прав, а libC++ - неправильный, согласно 22.4.2.1.2 стандарта (2011).

На этапе 2

Если это [символ - нм], не отбрасываются, а затем выполняется проверка, чтобы определить, если с допускается в качестве следующего символа входного поля спецификатора преобразования возвращаемого по Этапу 1 ["% g" в этом случае - nm]. Если это так, он накапливается.

Поскольку %g спецификатор преобразования не допускает d или X символов, символ не накапливается. Он также не отбрасывается (только символы разделителя групп могут быть отброшены). Поэтому этап 2 должен завершиться на этом этапе.

Затем на этапе 3 скопированные символы преобразуются.

Похоже, что libC++ ошибочно накапливает d и X на этапе 2, затем пытается их преобразовать, и это не удается.

+0

Я сообщил о проблеме с ребятами из libC++. См. Bug [17782] (http://llvm.org/bugs/show_bug.cgi?id=17782) –

+0

Появляется только в том случае, если завершающий символ «A» .. «F», «I», «N» , 'P' и 'X' (и те же символы в нижнем регистре) –

+0

@MarshallClow: OK, от A до F и X могут появляться в шестнадцатеричных числах, и они фактически отображаются в соответствующей части стандарта, поэтому можно было бы, вероятно, посмотрите, где все пошло не так, если это были единственные виновники. Но как я, N и P вступили в игру? –