Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't it possible to cast an int (representing an ASCII character) to an std::string without curly braces wrapped around the int?

int main() {

    std::string A;
    A += (std::string)65;
    std::cout << A;

}

The code above does not work. It throws a compiler error. But the code below works.

int main() {

    std::string A;
    A += (std::string){65};
    std::cout << A;

}

When I wrap the 65 in curly braces, it is interpreted as an ASCII A like I wanted it to be, but without the curly braces, the program doesn't work. I also tried putting multiple numbers in the braces, like so:

int main() {

   std::string A;
   A += (std::string){65, 66};
   std::cout << A;

}

That would print out AB. I just hope someone can clear this up for me.

like image 488
Greg M Avatar asked Apr 21 '15 07:04

Greg M


3 Answers

The second and third work because of this constructor:

basic_string( std::initializer_list<CharT> init, 
              const Allocator& alloc = Allocator() );

That is, whenever the compiler sees the curly braces, it converts {...} into an std::initializer_list<T> for a suitable T.

In your case, it converts to std::initializer_list<char> which then gets passed to the above mentioned constructor of std::string.

Since there exists an overload of += which takes std::initializer_list<char>:

basic_string& operator+=( std::initializer_list<CharT> ilist );

you can write this:

std::string s;

s += {65};
s += {66, 67};

That should work as well.

Note that you can also write this:

s += 65;

Even this will work, but for a different reason — it will invoke the following overload:

basic_string& operator+=( CharT ch );

In this case, 65 (which is int) converts into char type.

Hope that helps.

like image 106
Nawaz Avatar answered Nov 15 '22 06:11

Nawaz


(std::string){65, 66} is a C99 compound literal, and not valid C++. Some C++ compilers support it as an extension, but they should all complain with sufficiently pedantic settings.

std::string{65, 66} (or just std::string{65}) works because they construct a temporary std::string using its initializer_list<char> constructor.

std::string has no constructor taking an integer (or a char, for that matter), so your cast doesn't work.

Also, A += 65; works as well, because string has an overloaded operator+= taking a char. (Unfortunately, this also means that A += 3.1415926; "works" too.)

And similarly, A += {65, 66}; will also work because string has an overloaded operator+= taking an initializer_list<char>.

like image 39
T.C. Avatar answered Nov 15 '22 05:11

T.C.


The expression (std::string)65 is a cast, i.e. you are trying to convert the number 65 to an std::string. Your first example doesn't work because an int is not convertible to an std::string , since std::string does not have any constructor that takes an integer.

Your second and third example work since A+= (std::string){65} means "construct a temporary string via its initializer-list constructor (no. 9 here) and append it to A". Note that you could've just written A+= {65}, and no temporary will be constructed, since you invoke directly std::string::operator+= on a initializer list, no. 4 here.

like image 31
vsoftco Avatar answered Nov 15 '22 06:11

vsoftco