Непоследовательное поведение потока строк при разборе удваивается в libc ++ и glibc - PullRequest
0 голосов
/ 12 февраля 2019

При компиляции следующего примера с gcc и clang ...

#include <sstream>
#include <iostream>

int main() {
    double val;
    std::stringstream ss("6.93758e-310");
    ss >> val;

    std::cout << "fail: " << ss.fail() << std::endl
}

... Я получаю другое поведение:

  1. При использовании gcc бит сбоя потока ss.fail() не устанавливается, в то время как
  2. для clang устанавливается

Может быть уместно отметить, что в обоих случаях errno установлен на ERANGE.

Кроме того, локально я получаю такое же поведение с clang и gcc, если только я явно не использую libc ++ с clang (-stdlib=libc++) вместо glibc.

Iя не уверен, что такое правильное поведение, но мне кажется, что оно должно быть последовательным.

1 Ответ

0 голосов
/ 15 февраля 2019

Поведение оператора извлечения входных потоков задается следующим образом:

[istream.formatted.arithmetic] Как и в случае вставок, эти экстракторы зависят от num_get<> ([локаль].num.get]) объект для выполнения анализа данных входного потока.Эти экстракторы ведут себя как отформатированные функции ввода (как описано в [istream.formatted.reqmts]).После того, как часовой объект создан, преобразование происходит, как если бы оно выполнялось следующим фрагментом кода:

using numget = num_get<charT, istreambuf_iterator<charT, traits>>;
iostate err = iostate::goodbit;
use_facet<numget>(loc).get(*this, 0, *this, err, val);
setstate(err);

В приведенном выше фрагменте loc обозначает закрытый член класса basic_ios.

[facet.num.get.virtuals] немного многословно, но соответствующие части:

Для двойного значения функция strtod.

... ifполе представляет значение вне диапазона представимых значений, ios_base :: failbit присваивается err.

strtod не указано в стандарте C ++, но в стандарте C.Соответствующий бит:

7.20.1.3 Функции strtod, strtof и strtold

§10 Если результат опустится (7.12.1), функции возвращают значение, величина которого равнане больше наименьшего нормализованного положительного числа в типе возврата;получает ли errno значение ERANGE, определяется реализацией.

Указанное правило:

7.12.1 Обработка состояний ошибки

§5 Результатнедопустимо, если величина математического результата настолько мала, что математический результат не может быть представлен без исключительной ошибки округления в объекте указанного типа. 204) Если результат недопустим, функция возвращает реализацию-определенное значение, величина которого не больше наименьшего нормализованного положительного числа в указанном типе;если целочисленное выражение math_errhandling & MATH_ERRNO отлично от нуля, то, получает ли errno значение ERANGE, определяется реализацией;если целочисленное выражение math_errhandling & MATH_ERREXCEPT отлично от нуля, то, вызвано ли исключение с плавающей запятой '' underflow '', определяется реализацией

204) Термин underflow предназначен для охвата обоих '' постепенного снижения ''как в IEC 60559, а также в «потоке с нулевым потоком».


Хотя C ++ не определяет способ представления операций с плавающей запятой, ваша система, вероятно, использует IEEE-754 (IEC60559).

IEEE-754 определяет нижний уровень как:

7.5.0 (упрощенный)

Исключение нижнего уровня должно сигнализироваться, когда крошечный ненулевой результатобнаружен.Это должно быть, когда ненулевой результат, вычисленный так, как если бы диапазон экспоненты и точность были неограниченными, находился бы строго между ± b emin .

, где ± b emin является положительным или отрицательным нормальным значением, ближайшим к нулю.В нем также говорится:

Исполнитель должен выбрать способ обнаружения жесткости


Итак, чтобы ответить на ваше утверждение:

itмне кажется, что он должен быть согласованным.

Это было бы неплохо, но большая часть поведения, связанного с недостаточным потоком, определена как определяемая реализацией.

Честно говоря, API входного потокаограничен, так как он не обеспечивает гарантированный доступ к округленному значению в случаях, когда обнаружен недостаточный поток, а также не обеспечивает способ отличить отказ нижнего уровня от других сбоев.

...