I always thought it would be handy to be able to write:
const std::string s = (std::ostringstream() << "hi" << 0).str();
This doesn't work in C++ by default because operator<<
returns the ostringstream
as a ostream
, which obviously doesn't have the str()
member.
I was pleasantly surprised though to discover that this can be done in C++11:
#include <iostream>
#include <sstream>
#include <string>
template <typename CharT, typename traits, typename T>
std::basic_ostringstream<CharT,traits>&& operator<<(std::basic_ostringstream<CharT,traits>&& out, const T& t) {
static_cast<std::basic_ostream<CharT,traits>&>(out) << t;
return std::move(out);
}
int main() {
const std::string s = (std::ostringstream() << "hi" << 0).str();
std::cout << s << std::endl;
}
It needs rvalue references and move semantics to bind the temporary to a reference here.
- Is there a good reason why this isn't provided by the standard library by default? Is it an oversight? Making this idiom legal code seems like it might offer a number of benefits.
- In my local C++11 project, I provide some "utility" code. Is there any reason why I shouldn't include this and use it widely?
How about the more generic version:
template <typename S, typename T, class = typename
std::enable_if<std::is_base_of<std::basic_ostream<typename S::char_type,typename S::traits_type>, S>::value>::type>
S&& operator<<(S&& out, const T& t) {
static_cast<std::basic_ostream<typename S::char_type,typename S::traits_type>&>(out) << t;
return std::move(out);
}