For people new to template resolution and template type deduction in C++, they may have written this code and get confused why it doesn’t compile:
#include <string>
int main()
{
std::string s;
s += 2; // compiles correctly
s = s + 2; // compiler error
return 0;
}
And here’s my answer:
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 an overloaded member function basic_string& operator+=(CharT)
, and string is just basic_string<char>
.
As values that fits in a shorter type can be interpreted as that type, in the 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, instead of the character '2'
(with ASCII value 50, or 0x32).
However, string does not have an overloaded member function like string operator+(int)
, so 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.
Leave a comment