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.
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.
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.
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.
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.
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