On cppreference.com, it says that the to_string
function could work in the following ways. Why isn't there char
and unsigned char
type?
to_string(int value);
to_string(long value);
to_string(long long value);
to_string(unsigned value);
to_string(unsigned long value);
to_string(unsigned long long value);
to_string(float value);
to_string(double value);
to_string(long double value);
CodePudding user response:
Why there isn`t char and unsigned char type?
Because there is already a std::string
constructor std::string::string(size_type, char)
that can take a char
. In particular, from basic_string
:
//-----------------------------vvvvv------------------->character type parameter
basic_string( size_type count, CharT ch,
const Allocator& alloc = Allocator() );
This means that instead of using to_string
, we can just use
std::string str(1, 'c');
that will use the above constructor.
Basically, we don't need an overload of to_string
for char
as std::string
already have the constructor available for it.
CodePudding user response:
The problem is with ambiguity. By applying to_string
to character 'a'(=97) do you want to get string "a" or string "97"?
If you want to get "a" then just use one of the constructors of the string. If you want "97" then apply to_string
after casting the character to an int
or some other integer type.
CodePudding user response:
The behavior of passing a char
or unsigned char
to std::to_string
is already what would be expected. Adding overloads will not change anything.
In principle just an overload for signed long long
and unsigned long long
would be sufficient to cover all integer types, since every integer type can be converted to one of these without the value being affected. Both of these overloads are required because unsigned long long
wouldn't be able to take negative values correctly and signed long long
is not able to represent the largest values that unsigned long long can
.
However, because the overload rules in C do not consider converting e.g. int
to signed long long
any better or worse than int
to unsigned long long
, you wouldn't be able to pass e.g. an int
directly to the function if only these two overloads were present. The call would be ambiguous:
void f(unsigned long long) {}
void f(signed long long) {}
int main() {
int x = 0;
f(x); // fails due to ambiguity
}
You need to add an overload for int
, unsigned int
, etc. as well:
void f(unsigned long long) {}
void f(signed long) {}
void f(unsigned long long) {}
void f(signed long) {}
void f(unsigned int) {}
void f(signed int) {}
int main() {
int x = 0;
f(x); // ok, prefers f(signed int) without conversion
}
However, no overloads for char
, unsigned char
, signed char
, signed short
and unsigned short
are required, because the C overload rules do consider conversions from these types to integral types with higher rank (i.e. int
and larger) differently.
A conversion from one of these types to int
, if int
is able to represent all of their values, or unsigned int
otherwise, is a so-called integral promotion and is considered better than any other conversion to any of the other integral type. So there will be no ambiguity in overload resolution even if there are no specific overloads for these types. They will always choose the int
or unsigned int
overload and their values will be represented faithfully.
void f(unsigned long long) {}
void f(signed long) {}
void f(unsigned long long) {}
void f(signed long) {}
void f(unsigned int) {}
void f(signed int) {}
int main() {
char x = 0;
f(x); // ok, chooses f(signed int) with integral promotion instead of integral conversion
}