As other answers mention, using an "end-of-message" marker is a good design.
But if you really need what you asked for, you can do it like this: You implement the EOM idea like you normally would, and then add this class:
class AutoEnd
{
private:
mutable Object & m_obj;
public:
explicit AutoEnd (Object & obj) : m_obj (obj) {}
~AutoEnd () {m_obj << EOM;}
Object & obj () const {return m_obj;}
};
template <typename T>
AutoEnd const & operator << (AutoEnd const & ae, T && arg)
{
ae.obj() << std::forward<T>(arg);
return ae;
}
And you can use it like this:
Object object;
...
AutoEnd(object) << argument1 << argument2 << argument3;
which will do what you want. Some notes:
- You can obviously still use the explicit
EOM
method after addingAutoEnd
. This gives you greater flexibility to use whichever method where it makes sense. - The key in this technique is the destructor for
AutoEnd
, which will be called at the end of the line it was instantiated in. - You can implement it better than above. Most importantly, it's a good idea to make the constructor of
AutoEnd
to be private or somehow signal the user that they should not create normal instances ofAutoEnd
, because they are useless that way and they keep references to youObject
s and may try to use them after they are destroyed. - You can only use this technique safely if
operator <<
forObject
doesn't throw an exception, because it's called inside a destructor and destructors should not throw. - Since
AutoEnd
is designed to be used as a temporary object, and you can only work withconst &
of temporary objects easily,operator <<
gets and returns a constant reference, and the storedObject
reference is declared asmutable
. In my opinion, this is not a bad design, sinceAutoEnd
objects don't have any internal state (apart from theObject &
) and the correctness of callingoperator <<
on that needs to be assured elsewhere (i.e.AutoEnd
doesn't need to care about that.) - You should make
AutoEnd
non-copyable.