The arithmetic extraction operator for std::basic_istream
has non-virtual overloads for all 8 integer types (not listing chars, which are handled differently anyway), and it calls num_get::get
, which has individual virtual overloads for 6 of them (missing signed versions of short and int)
The arithmetic insertion operator for std::basic_ostream
also has non-virtual overloads for all 8 integer types, and it calls num_put::put
, which only has virtual overloads for 4 types, which are long
, long long
and their unsigned variants. For the smaller types, the insertion operator performs integer promotions.
Why a gap in what is otherwise a tour-de-force of user extensibility? Is seems impossible to provide user-defined handling for each integer type (e.g. to build a type-preserving serialization library on top of iostream interface), and moreso, it is asymmetric. It could have been achieved with little effort. Is there a trade-off?
According to Standard C++ Iostreams and Locales:
At first sight it might look as if versions of put() for short, int, or float are missing. The intent was to keep the interface of the standard library concise, and a value of type short or int can be handled by the version of long. Similarly, a value of type float can be handled by the put() version of double.
and then later on about num_get::get()
:
Again, as with num_put::put(), the types that are not absolutely necessary are omitted.
When you're reading values you have to allow for overflows, so need an extractor for each type. When you're writing values you don't, so the largest type is sufficient. Back in the olden days the largest type was long
. When long long
was added, the version for long
was kept for backward compatibility.
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