The way EV
is currently written, it will generate a new object on each call. But that creation doesn't have to be of an object of the same type as what is ultimately passed to SendEvent. That's because the textual nature of preprocessor macros and more complex expressions adds some tricks. Consider this:
class dummy {
private:
static dummy* freeme;
public:
dummy() { freeme = this; }
static bool dofree() { delete freeme; return true; }
};
dummy* dummy::freeme;
CEvent *ev = new CEvent(this);
EV( dummy && dummy::dofree() ? ev : NULL );
That will expand out so that the new you're running is not of a CEvent, but of a dummy class...which you then free, and then the whole expression evaluates to your event:
SendEvent( new dummy && dummy::dofree() ? ev : NULL );
(Note: Using ?: is not as nice as the comma operator, so there's a wasted NULL branch here that never actually happens. The comma operator would be nice, but preprocessor macros treat commas specially and this is one of the cases where it can't be used. Making it thread-safe is left as an exercise for the reader.)
To make it "cleaner" but still express it in terms of EV
...without explicitly mentioning SendEvent
at all, you could make your own macro:
#define EV2(event) EV( dummy && dummy::dofree() ? event : NULL )
...or you could just use SendEvent since it seems to do exactly what you want. But where's the fun in that? ;-P
UPDATE:
As @AlfPSteinbach points out, a more esoteric but lightweight way of turning your new
into a no-op is with placement new:
int dummy;
CEvent *ev = new CEvent(this);
EV( (&dummy) int ? ev : NULL );
So now you're expanding into:
SendEvent( new (&dummy) int ? ev : NULL );
You're executing a new, but this time without needing to worry about freeing the result! Because I wasn't entirely sure if this was kosher esp. in threading cases, I made its own question:
Is it well-defined/legal to placement-new multiple times at the same address?