Chaining methods and temporary variables, please clarify
-
27-09-2019 - |
Question
Greetings, everyone!
I have a class that receives a pointer to a "circle" (for example) and then adjusts its attributes via some "chaining" methods. Something like this:
class CCircleSetter
{
public:
explicit CCircleSetter( CCirclePtr circle ) : m_circle(circle)
{
}
CCircleSetter & Radius( int radius )
{
if (m_circle) m_circle->SetAttribute( "radius", radius );
return *this;
}
CCircleSetter & Center( CPoint center )
{
if (m_circle) m_circle->SetAttribute( "center", center );
return *this;
}
operator bool() const
{
return ( m_circle != NULL );
}
private:
CCirclePtr m_circle;
};
Now I wonder whether this code is legal or not:
if ( CCircleSetter(myCircle).Radius(10).Center(myPoint) )
{ ... }
On the one hand, I think that temporary object, created inside "if" expression, will live until the end of this expression. So, the calls to "Radius" and "Center" are legal. But on the other hand, it is an undefined behavior to use references to temporary variables and it seems to me that I am doing exactly this kind of thing - using (*this), where "this" is a temporary. It gives me some doubts, so, please, clarify. Thanks!
Solution
No, that's fine in this very specific case, because the temporary will be destroyed AFTER the whole line will execute, but in general is very bad to hold references to temporaries.
OTHER TIPS
Even if it's a temporary variable, that doesn't mean that all of its members are temporary. Inside the scope of your temp object, the this
pointer and other members are not temporary. Your code is completely fine. Now if you did something like:
SomeFunc(&CCircleSetter(myCircle))
this would be a reference to a temp variable.
I don't think it's that a reference to a temporary is undefined, it's just forbidden. Also, I believe this only applies to function arguments. Visual Studio will allow you to pass references to non-const temporaries on the default warning/error level, though I know gcc will not.
As far as I know, doing so is only forbidden so programmers don't shoot themselves in the foot by storing a reference to a temporary that goes out of scope. Considering this is C++, I find that quite stupid.
I don't see any problem with what you're doing.
What you're doing is basically the same as in
if( istrm >> a >> b ) ...
which is the same as
if( istream.operator>>(a).operator>>(b).operator some_bool_like_type() )
I think this is fine from a usability POV. (There certainly are no syntactic/semantic problems with it.)
However, as always, implicit conversion to bool is a bit nasty, because it allows unexpected code to compile:
if ( CCircleSetter(myCircle).Radius(10) != 10 )