Home > Enterprise >  Why doesn`t C to_string function support char and unsigned char type?
Why doesn`t C to_string function support char and unsigned char type?

Time:10-23

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
}
  •  Tags:  
  • c
  • Related