Reputation:
Simple utility function to convert a value to std::string while keeping backwards compatibility.
Probably a silly question, but I'm curious to hear some opinions about it or if there are any flaws in doing so this way:
template<typename T>
std::string toString(T parm)
{
#ifdef CXX11_AVAILABLE
return std::to_string(parm);
#else
std::ostringstream stream;
stream << parm;
return stream.str();
#endif
}
Will it create a copy in memory if I do it like that?
Thanks in advance for your answers :)
Upvotes: 1
Views: 210
Reputation: 131646
A few points:
First, instead of #ifdef CXX11_AVAILABLE
you want to check if __cplusplus > 201103L
; for an explanation, see:
http://stackoverflow.com/questions/11053960/ddg#11054055
Now, you're going to have at least one copy anyway, just by piping the string into the ostringstream
, regardless of which C++ version you're using.
Also, you're going to be creating and destroying an ostringstream
with every damn call to toString()
- that's terrible! ... at least do:
namespace detail {
inline std::ostringstream& get_ostringstream(){
static thread_local std::ostringstream stream;
stream.str("");
stream.clear();
return stream;
}
} // namespace detail
and then in toString()
, replace
std::ostringstream oss;
with
std::ostringstream& oss = detail::get_ostringstream();
Finally, remember that the final copy - the oss.str()
is subject to Return Value Optimization (RVO), which in C++17 is mandatory and for earlier standard was applied by most compilers. So if you initialize a string with the result of the function, the construction of the oss.str()
copy would take place at the address of that outside string.
Edit: Actually, if this is performance-critical code, you should just not be using general-purpose string conversion functions, and possibly not use std::string
at all. Of course - before customizing anything, profile and check where you're hurting performance-wise.
Upvotes: 1