According to answers to this questions Is overloading on all of the fundamental integer types is sufficient to capture all integers? overloading of all fundamental types may not be able to handle types like int8_t int64_t etc. On another side according to documentation std::ostream formatted output and std::istream formatted input is implemented exactly by overloading all fundamental types. So on platform where int8_t and others could not be handled by such overloading how C++ streams would have to handle them? Would it fail to compile? Would standard library implementors have to provide additional undocumented methods? Something else?
For integer types, [istream] defines:
basic_istream<charT,traits>& operator>>(bool& n);
basic_istream<charT,traits>& operator>>(short& n);
basic_istream<charT,traits>& operator>>(unsigned short& n);
basic_istream<charT,traits>& operator>>(int& n);
basic_istream<charT,traits>& operator>>(unsigned int& n);
basic_istream<charT,traits>& operator>>(long& n);
basic_istream<charT,traits>& operator>>(unsigned long& n);
basic_istream<charT,traits>& operator>>(long long& n);
basic_istream<charT,traits>& operator>>(unsigned long long& n);
Any code of the form is >> x may fail to compile if x is an integer type that's not in that list.
As a quality of implementation issue, an implementation which offers extended integer types could add operator>> overloads for those types. This is permitted by [member.functions]/2 (as noted by hvd in comments), talking about classes in the standard library:
An implementation may declare additional non-virtual member function signatures within a class:
[...]
- by adding a member function signature for a member function name.
A call to a member function signature described in the C ++ standard library behaves as if the implementation declares no additional member function signatures.
This is a stronger guarantee than the general rule that implementations may add extensions that don't break conforming programs. The behaviour of conforming programs using SFINAE might be affected by the presence of the extra overloads.
For output, integer types not in the list will be implicitly convertible to another integer type which is in the list.
So on platform where
int8_tand others could not be handled by such overloading how C++ streams would have to handle them?
As far as integer insertion is concerned (operator<<), it would handle them in accord with standard C++ overload resolution. Extended integer types are still integer types and follow the rules of implicit conversion for the purpose of overload resolution.
For example, int8_t can be upconverted to any signed integer type large enough to hold it. So if int8_t is an extended integer type rather than an alias of the standard integer types, it can be upconverted to one of the standard ones, in accord with overload resolution rules.
For integer extraction (operator>>), this requires a non-const reference to a live integer, so conversion is not possible. Therefore, if you do not provide one of the explicit types that operator>> is overloaded for, your code should fail to compile.
The best you might get is if an implementation adds overloads specifically for those types, but you can't rely on that.
It should be noted that C++17's new to_chars and from_chars are explicitly stated by the standard to have overloads for all signed&unsigned integer types (and char). So that includes extended integer types.
Would it fail to compile?
For insertion, that depends on the types used. int8_t is safe because there are standard integer types that are larger than it. It may have different behavior than you expect, but it will work.
By contrast, there is no guarantee that int_least64_t or intmax_t is not larger than long long. And implicit conversion can't go from larger to smaller. In those cases, you get a compile error.
For extraction, you get compilation failures if you don't match the types.
Would standard library implementors have to provide additional undocumented methods?
No. They are permitted to do so, but that's not something you can rely on.
int8_t is a special case because of the treatment of how it can be implemented.
char serves double duty as a byte-sized type and a character type. Because it's a character type, iostream operations will treat uses of char differently from how it treats integer types. With integers, it will parse/generate integer strings. With a character, it assumes you mean to read a character.
A valid implementation of int8_t could be as an alias of signed char or just char if it is signed. As such, use of it with stream operations will treat it as a character.
A valid implementation of int8_t could be as an extended integer type, a type which is distinct from char. As such, the value will be upconverted to a larger integer type that matches one of the standard ones, in accord with overload resolution rules. And therefore, it will call one of these.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With