DeMarcus said:
Now, I've upgraded to 4.5.0 and, as you say, get following error:
error: invalid initialization of reference of type 'std:
stream&&'
from expression of type 'std:
stream'
I'm trying to understand the rvalue reference better. Would my
delegator template work?
template<typename T>
inline std:
stream&& operator<<( std:
stream&& s, const T& t )
{
return std::move( operator<<( s, t ) );
}
I'm getting a little lost here. Every now and then you switch
(seemingly randomly) between examples that use what I have supposed is
your custom stream, class A, and then similar examples using
std:
stream&(&), as here. For example, in an earlier post you
presented the following as your `delegator'.
Since, at each change, you present only snippets of code, it is very
important, in order to maintain context in my own mind, that I can make
assumptions about what I have seen already. Effectively, I am forced to
ask: "So, which /is/ your delegator?"
I say this because I think it makes a difference to this whole
discussion whether we are talking about some custom stream that you are
building or the std:
stream. You seem intent on wanting to make
copious use of temporary instances of your stream class and pass these
around using rvalue references. That is fine, but I certainly wouldn't
want to use this method for std:
stream. The reason being that, in
your own type, you are able to support your requirements by adjusting
how you implement your type. std:
stream, on the other hand, is not
necessarily - actually, almost certainly not - implemented to fit in
well with your intensions.
It compiles and runs under gcc 4.5.0, but there are two things that I
can't calculate in my head:
1. Is this a valid treatment of the ostream s? I mean, I'm not allowed
to provide a temporary to a non-const ref, but here it apparently
works. Would this be the proper solution?
What is it that leads you to want to pass around temporary objects of
class std:
stream in the first place? This is not how it is
conventionally done. Again, I might ask the same question of the
design of your custom stream class. Stream class are surely not cheap
to copy, and perhaps not even that cheap to move.
Overall, I can't help thinking that all your problems, or issues, would
simply disappear if you gave up wanting to use A() << b. Certainly I
have not yet, in this discussion, been able to gain a sense of its
purpose or value.
template<typename T>
inline std:
stream&& operator<<( std:
stream&& s, const T& t )
{
std:
stream s2( s ); // if future ostreams get move semantics
operator<<( s2, t );
return std::move( s2 );
}
2. Why don't I get an infinite recursion as you suggested in an
earlier post? I tried to clarify for the compiler which function I was
looking for with following.
In the body of the op<< function above, the rvalue reference parameter s
behaves as an lvalue. (This was one of the key changes to the current
implementation, IIUC). Thus, it's presence in the return statement
return operator<<( a, t );
will select an overload that accepts an lvalue as its first argument, if
one is available (as, I would suggest, there clearly is).
template<typename T>
inline std:
stream&& operator<<( std:
stream&& s, const T& t )
{
return std::move( operator<< <S&, const T&>( s, t ) );
} ^
|
What is `S' here ------------------
but got
error: no matching function for call to 'operator<<(std:
stream&,
const B&)'
That is strange since that function does exist.
Again, a *complete* compilable example would be necessary here in order
to permit me to comment on this.
How do I convert a SomeClass&& to a SomeClass& ? It's not possible
unless SomeClass has move semantics, right?
Under what circumstances would you want to do this, given the
fundamental difference between rvalue references (as, effectively,
temporary objects) and lvalues (as named regions of addressable
object storage)?
Regards
Paul Bibbings