Reputation: 2921
#include <iostream>
#include <sstream>
template <typename T>
const char* numberToString(T number) {
std::ostringstream ss;
ss << number;
return ss.c_str();
}
int main() {
printf(numberToString(123));
return 0;
}
My error:
1>d:\programming\euler\problem 4\problem 4\problem 4\source.cpp(8): error C2039: 'c_str' : is not a member of 'std::basic_ostringstream<char,std::char_traits<char>,std::allocator<char>>'
1> d:\programming\euler\problem 4\problem 4\problem 4\source.cpp(26) : see reference to function template instantiation 'const char *numberToString<int>(T)' being compiled
1> with
1> [
1> T=int
1> ]
Why doesn't this work?
Upvotes: 3
Views: 1770
Reputation:
You want to do:
template <typename T>
std::string numberToString(T number) {
std::ostringstream ss;
ss << number;
return ss.str();
}
int main() {
std::cout << numberToString(123);
return 0;
}
To get the underlying std::string
in std::ostringstream
, and then the resulting c-style string in std::string
. As others have pointed out, the pointer returned by c_str
goes out of scope, and therefore you must copy it to a buffer or to another std::string
. If you insist on using printf
, then use c_str
on the function call:
printf("%s", numberToString(123).c_str());
For more information, see Is it a good idea to return " const char * " from a function?
Depending on what somestlstring is and what is being done there.
If it is a local variable you are returning a pointer into memory that is being released when GetSomeString completes, so it is a dangling pointer and an error.
It all boils down to the lifetime of somestlstring and the operations you perform on it. The pointer returned by .c_str() is guaranteed to be valid only up to the next mutating operation in the string. So if something changes somestlstring from the call to .c_str() and before s is constructed you will be in undefined behavior land.
However, you can simply use std::to_string
.
std::string s = std::to_string(123);
Upvotes: 2
Reputation: 12907
That's because c_str()
is the member function of std::string
which returns a const char*
.
To get the underlying string of a strinstream, you must use str()
.
The error was pretty much self explanatory:
error C2039: 'c_str' : is not a member of 'std::basic_ostringstream
Note however that you're returning a pointer to something (the underlying data of the temporary string returned by str()
) that will not exist after the return statement (i.e. in the calling code) and that manipulating that pointer will quite sureley end up in undefined behavior.
As you are in C++, you could rather return the std::string
directly, and output it with
std::cout << numberToString(123);
which would be safer.
Upvotes: 2
Reputation: 15872
c_str()
does not exist for std::ostringstream
. What you meant was:
template <typename T>
const char* numberToString(T number)
{
std::ostringstream ss;
ss << number;
return ss.str().c_str();
}
After you make that change, you will have another problem: you will be returning a pointer to a buffer that was just destroyed. To fix that, you should return a std::string
:
template <typename T>
std::string numberToString(T number)
{
std::ostringstream ss;
ss << number;
return ss.str();
}
Which you can do with std::to_string
already, so it is really pointless to write your own function.
Upvotes: 4
Reputation: 22020
c_str
is a member of std::string
, not ostringstream
. If you want to get a string
out of the stream, use str()
. Note, however, that returning a const char*
from that string
is wrong - the string
will go out of scope before you can use the const char*
. Therefore, have your function return a string
(or have it get a buffer to write to):
template <typename T>
std::string numberToString(T number) {
std::ostringstream ss;
ss << number;
return ss.str();
}
Upvotes: 7