I\'m thinking about a problem which has some similarity with perfect forwarding, but where the function argument is not passed to a called function, but returned. This is why I
std::ostringstream()
is an rvalue, butoperator<<
takes an lvalue as first argument
There's a generic inserter to take rvalue streams, but it returns a basic_ostream<charT, traits>&
:
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
To work correctly for your example it would have to return the derived type of the stream (std::ostringstram
).
- Is the output operator as I wrote it indeed working as expected (and fulfilling all the requirements I gave)? Or could it fail in unexpected ways or have other unexpected consequences? Especially: Is my use of
std::forward
correct here?
Your code looks correct to me.
- Is there an easier way to meet the requirements?
Your code looks similar to the code I wrote to solve this problem (see below).
- Assuming this is indeed correct and the simplest way to do it: Do you consider it a good idea to do that, or would you advice against it (both specifically for stream output as in my example, and as a more general scheme for passing objects through functions)?
The idiom looks fine to me.
In libc++ I defined the rvalue ostream inserter like the following (as an extension). I made an attempt to get it standardized but it was late and the committee was understandably not in the mood for more thrashing:
template <class _Stream, class _Tp>
inline
typename enable_if
<
!is_lvalue_reference<_Stream>::value &&
is_base_of<ios_base, _Stream>::value,
_Stream&&
>::type
operator<<(_Stream&& __os, const _Tp& __x)
{
__os << __x;
return std::move(__os);
}
Unlike yours, this only accepts rvalue streams. But like yours, it returns the concrete derived type, and so works with your example.