Гарантировано ли, что std::char_traits <char> ::to_int_type(c) == static_cast <int> (c)?
Вопрос Как правильно использовать возвращаемое значение из <tcode id="238412"></tcode> и <tcode id="238413"></tcode>? заставил меня задуматься, гарантировано ли это
std::char_traits<char>::to_int_type(c) == static_cast<int>(c)
для всех допустимых значений.
Это встречается во многих местах. Например,
istream::peek
звонки
streambuf::sgetc
, который использует
to_int_type
преобразовать значение в
int_type
. Это действительно означает, что следующий символ
\n
?
Вот мой анализ. Соберем кусочки из [char.traits.require] и [char.traits.specializations.char] :
Для каждого значения
to_char_type(e)
возвращается, если для некоторых;
некоторое неуказанное значение в противном случае.
Для каждой пары значений и,
eq_int_type(e, f)
возвращается, если и для некоторых и;
true
, если и;false
, еслиe == eof()
xorf == eof()
;не указано иное.
eof()
возвращает такое значение, что!eq_int_type(e, to_int_type(c))
для всех .если только
(unsigned char) c == (unsigned char) d
.
Теперь рассмотрим эту гипотетическую реализацию: (синтаксически упрощено)
// char: [-128, 127]
// unsigned char: [0, 255]
// int: [-2^31, 2^31-1]
#define EOF INT_MIN
char to_char_type(int e) {
return char(e - 1);
}
int to_int_type(char c) {
return int(c) + 1;
}
bool eq(char c, char d) {
return c == d;
}
bool eq_int_type(int c, int d) {
return c == d;
}
int eof() {
return EOF;
}
Обратите внимание, что
(свойство 1) преобразование из в сохраняет ценность;
(свойство 2) преобразование из в
unsigned char
биективен.
Теперь проверим требования:
Для каждого значения, если
eq_int_type(e, to_int_type(c))
для некоторых тогдаe == int(c) + 1
. Следовательно,to_char_type(e) == char(int(c)) == c
.Для каждой пары
int
значенияe
иf
, еслиe == to_int_type(c)
иf == to_int_type(d)
для некоторых, а затемeq_int_type(e, f)
если толькоint(c) + 1 == int(d) + 1
если толькоc == d
(по свойству 1). Случаи EOF также легко поддаются проверке.Для каждого значения
int(c) >= -128
, такint(c) + 1 != EOF
. Следовательно,!eq_int_type(eof(), to_int_type(c))
.Для каждой пары
char
значенияc
иd
,eq(c, d)
если только(unsigned char) c == (unsigned char d)
(по свойству 2).
Означает ли это, что эта реализация соответствует требованиям, и поэтому
std::cin.peek() == '\n'
не делает то, что должен делать? Я что-то пропустил в своем анализе?
1 ответ
Означает ли это, что эта реализация соответствует требованиям, и поэтому std ::cin.peek() == '\n' не выполняет того, что должен делать?
Я согласен с твоим анализом. Это не гарантировано.
Похоже, вам придется использовать
eq_int_type(std::cin.peek(), to_int_type('\n'))
чтобы гарантировать правильный результат.
PS Ваш
to_char_type(EOF)
имеет неопределенное поведение из-за подписанного переполнения в
INT_MIN - 1
. Конечно, в этом случае значение не указано, но у вас по-прежнему не может быть UB. Это было бы верно:
char to_char_type(int e) {
return e == EOF
? 0 // doesn't matter
: char(e - 1);
}
to_int_type
будет иметь UB в системах, где int и char имеют одинаковый размер в случае
c == INT_MAX
, но вы исключили системы с гипотетическими размерами.