The question How to use correctly the return value from std::cin.get()
and std::cin.peek()
? made me wonder if it is guaranteed that
std::char_traits<char>::to_int_type(c) == static_cast<int>(c)
for all valid char
values c
.
This comes up in a lot of places. For example, istream::peek
calls streambuf::sgetc
, which uses to_int_type
to convert the char
value into int_type
. Now, does std::cin.peek() == '\n'
really mean that the next character is \n
?
Here's my analysis. Let's collect the pieces from [char.traits.require] and [char.traits.specializations.char]:
For every
int
valuee
,to_char_type(e)
returnsc
, ifeq_int_type(e, to_int_type(c))
for somec
;some unspecified value otherwise.
For every pair of
int
valuese
andf
,eq_int_type(e, f)
returnseq(c, d)
, ife == to_int_type(c)
andf == to_int_type(d)
for somec
andd
;true
, ife == eof()
andf == eof()
;false
, ife == eof()
xorf == eof()
;unspecified otherwise.
eof()
returns a valuee
such that!eq_int_type(e, to_int_type(c))
for allc
.eq(c, d)
iff(unsigned char) c == (unsigned char) d
.
Now, consider this hypothetical implementation: (syntactically simplified)
// 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;
}
Note that
(property 1) the conversion from
unsigned char
toint
is value-preserving;(property 2) the conversion from
char
tounsigned char
is bijective.
Now let's verify the requirements:
For every
int
valuee
, ifeq_int_type(e, to_int_type(c))
for somec
, thene == int(c) + 1
. Therefore,to_char_type(e) == char(int(c)) == c
.For every pair of
int
valuese
andf
, ife == to_int_type(c)
andf == to_int_type(d)
for somec
andd
, theneq_int_type(e, f)
iffint(c) + 1 == int(d) + 1
iffc == d
(by property 1). The EOF cases are also trivially verifiable.For every
char
valuec
,int(c) >= -128
, soint(c) + 1 != EOF
. Therefore,!eq_int_type(eof(), to_int_type(c))
.For every pair of
char
valuesc
andd
,eq(c, d)
iff(unsigned char) c == (unsigned char d)
(by property 2).
Does that mean this implementation is conforming, and therefore std::cin.peek() == '\n'
does not do what it is supposed to do? Did I miss anything in my analysis?