Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Append int to std::string

Tags:

c++

stdstring

I tried two different ways to append an int to a std::string, and to my surprise, I got different results:

#include <string>  int main() {     std::string s;     s += 2;     // compiles correctly     s = s + 2;  // compiler error      return 0; } 

Why does it compile and work correctly when I use the += operator, but fail when I use the + operator?

I don't think the question is like How to concatenate a std::string and an int?

In that question,no answer uses += operator.And the difference between += and + operator of std::string is the key to solve my doubt.

Frankly,the question is a good example for explaining why c++ is so difficult to master.

like image 406
navylover Avatar asked Aug 04 '17 11:08

navylover


People also ask

How do you add an int to a string?

To concatenate a string to an int value, use the concatenation operator. Here is our int. int val = 3; Now, to concatenate a string, you need to declare a string and use the + operator.

Can we append integer in string?

If you want to concatenate a string and a number, such as an integer int or a floating point float , convert the number to a string with str() and then use the + operator or += operator.


2 Answers

TL;DR operator+= is a class member function in class string, while operator+ is a template function.

The standard class template<typename CharT> basic_string<CharT> has overloaded function basic_string& operator+=(CharT), and string is just basic_string<char>.

As values that fits in a lower type can be automatically cast into that type, in expression s += 2, the 2 is not treated as int, but char instead. It has exactly the same effect as s += '\x02'. A char with ASCII code 2 (STX) is appended, not the character '2' (with ASCII value 50, or 0x32).

However, string does not have an overloaded member function like string operator+(int), s + 2 is not a valid expression, thus throws an error during compilation. (More below)

You can use operator+ function in string in these ways:

s = s + char(2); // or (char)2 s = s + std::string(2); s = s + std::to_string(2); // C++11 and above only 

For people concerned about why 2 isn't automatically cast to char with operator+,

template <typename CharT>   basic_string<CharT>   operator+(const basic_string<CharT>& lhs, CharT rhs); 

The above is the prototype[note] for the plus operator in s + 2, and because it's a template function, it is requiring an implementation of both operator+<char> and operator+<int>, which is conflicting. For details, see Why isn't automatic downcasting applied to template functions?

Meanwhile, the prototype of operator+= is:

template <typename CharT> class basic_string{     basic_string&       operator+=(CharT _c); }; 

You see, no template here (it's a class member function), so the compiler deduces that type CharT is char from class implementation, and int(2) is automatically cast into char(2).


Note: Unnecessary code is stripped when copying from C++ standard include source. That includes typename 2 and 3 (Traits and Allocator) for template class "basic_string", and unnecessary underscores, in order to improve readability.

like image 88
iBug Avatar answered Sep 24 '22 22:09

iBug


s += 2; is not doing what you think it's doing. It calls the overloaded += operator to a char. It does not append the character '2', but rather the character with value 2, and the result will depend on the encoding used on your platform.

There is no operator overload defined to allow s + 2 to compile1. Hence the error.

The solution in both cases is to use std::to_string(2) rather than the int literal 2.


1 Essentially the reason is because operator+= is not a template function, but std::operator+ is, and overload resolution will favour a non-template function over a template one.

like image 30
Bathsheba Avatar answered Sep 23 '22 22:09

Bathsheba