Re: Overloaded Streaming Technique
Eric Hill wrote:
I'm trying to come up with a good method to accomplish conditional
streaming. Specifically, I would like to not incur the cost of
computing the stream parameters if the stream itself is disabled.
[...]
// get_some_data will NOT be called
options.enable = false;
example << stream_options << get_some_data();
What you want is essentially a short-circuit behavior, which can only be
achieved by the built-in &&, || and ? : operators. In a normal function
call it is impossible to prevent the evaluation of all input arguments.
Here's an example that demonstrates short-circuit evaluation:
class MyStream
{
public:
MyStream(bool initial_enabled = true) : enabled(initial_enabled) { }
operator bool() const { return enabled; }
void Enable() { enabled = true; }
void Disable() { enabled = false; }
private:
bool enabled;
};
struct EnableMyStream
{
};
struct DisableMyStream
{
};
MyStream& operator<<(MyStream& stream, DisableMyStream&)
{
return stream;
}
MyStream& operator<<(MyStream& stream, int value)
{
return stream;
}
int Get()
{
static int counter = 0;
return counter++;
}
void Test()
{
MyStream stream;
stream << Get() && stream << Get() && stream << DisableMyStream() &&
stream << Get();
}
In this case, Get() is only evaluated twice. After the stream is
disabled, the last && segment is skipped.
I'm not sure if I'd recommend using this syntax. You could just do an
if() with less overhead (no operator bool()) and better code readability:
if(! disabled) stream << Get() << Get();
If you think about overriding operator&& to implement something like this:
MyStream& operator&&(MyStream& stream, int value)
{
return stream;
}
stream && Get() && Get() && DisableMyStream() && Get();
Then I have bad news for you: Only the built-in operators provide
short-circuit behavior. Your custom overloaded operator&& would behave
like any other conventional function (like operator<<).
Tom