Append int to std::string
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.
Append an integer to std::wstring gives an error
The regular std::ostringstream
is not wide. The wstring
would like to be assigned a wide string.
You'll need std::wostringstream
Why is appending an int to a std::string undefined behavior with no compiler warning in C++?
The problem is that in
logger->info("i has the following value: " + i);
you are not working with std::string
. You are adding an int
to a string literal, ie a const char[]
array. The const char[]
decays into a const char*
pointer in certain contexts. In this case, the int
advances that pointer forward by 1337 characters, which is way beyond the end of the string literal, and therefore undefined behavior.
You should get a better compiler that warns you about this, ie:
foo.cc:7:42: warning: offset ‘1337’ outside bounds of constant string [-Warray-bounds]
7 | foo("i has the following value: " + i);
| ^
You can use a std::string
literal like this:
#include <string>
using namespace std::literals;
void foo(std::string);
void bla() {
int i = 1337;
foo("i has the following value: "s + i);
}
and then you get a "nicer" error that "std::string + int" isn't a thing in C++:
foo.cc:8:40: error: no match for ‘operator+’ (operand types are ‘std::__cxx11::basic_string<char>’ and ‘int’)
8 | foo("i has the following value: "s + i);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~
| | |
| std::__cxx11::basic_string<char> int
...
going on for 147 lines
After this, it should be obvious that what you want is this instead:
logger->info("i has the following value: "s + std::to_string(i));
Using std::string
literals avoids mistakes like this, because it turns warnings (which your compiler doesn't even give) into hard errors, forcing you to write correct code. So I recommend using the s
suffix for all strings.
Easiest way to convert int to string in C++
C++11 introduces std::stoi
(and variants for each numeric type) and std::to_string
, the counterparts of the C atoi
and itoa
but expressed in term of std::string
.
#include <string>
std::string s = std::to_string(42);
is therefore the shortest way I can think of. You can even omit naming the type, using the auto
keyword:
auto s = std::to_string(42);
Note: see [string.conversions] (21.5 in n3242)
How to add integer in a string?
Do something like
#include <string>
// ...
std::string s( "February " );
s += std::to_string( day );
Here is a demonstrative program
#include <iostream>
#include <string>
int main()
{
std::string s( "February " );
int day = 20;
s += std::to_string( day );
std::cout << s << '\n';
}
Its output is
February 20
Another approach is to use a string stream.
Here is one more demonstrative program.
#include <iostream>
#include <sstream>
#include <string>
int main()
{
std::ostringstream oss;
int day = 20;
oss << "February " << day;
std::string s = oss.str();
std::cout << s << '\n';
}
Its output is the same as shown above.
Concatenation of std::string and int leads to a shift. Why?
Does the string for some reason get converted into char[]
Actually it is the other way around. "iteration_"
is a char[11]
which decays to a const char*
when you add 1
. Incrementing the pointer by one makes it point to the next character in the string. This is then used to construct a temporary std::string
that contains all but the first character.
The documentation you link is for operator+
of std::string
, but to use that you need a std::string
first.
Related Topics
How to Know the Exact Line of Code Where an Exception Has Been Caused
C++ "Cin" Only Reads the First Word
How Does a C++ Reference Look, Memory-Wise
Append an Int to a Std::String
String Literal Address Across Translation Units
C++ Implicit Copy Constructor For a Class That Contains Other Objects
Why Switch/Case and Not If/Else If
How to Include Openssl in Visual Studio
Convert Cstring to Const Char*
How to Detect Win32 Process Creation/Termination in C++
Vector Size - 1 When Size Is 0 in C++
Resolving Ambiguous Overload on Function Pointer and Std::Function For a Lambda Using + (Unary Plus)
Can Placement New For Arrays Be Used in a Portable Way
Static_Assert Fails Compilation Even Though Template Function Is Called Nowhere
Does Mingw-W64 Support Std::Thread Out of the Box When Using the Win32 Threading Model