Friday, September 14, 2007

Our Predicated Construction Library

Introducing our predicated construction library that eases conditional usage of sentry (RAII) classes.

Motivating example:

Suppose you have a sentry class that enables wireframe rendering mode in some Direct3D context and upon destruction reverts solid fill.


struct WireframeSentry
{
   WireframeSentry(IDirect3DDevice9* device)
   : m_Device(device)
   {
      m_Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
   }

   ~WireframeSentry()
   {
      m_Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
   }

private:
   IDirect3DDevice9* m_Device;
};


The question is - how can you enable wireframe rendering through the sentry if it's optional, as in you want to enable wireframe rendering based on some external predicate. Obviously you can't optionally skip the constructor of a locally instantiated object.

if (renderInWireframe)
   WireframeSentry(device);


We can do so if, for example we provide a second bool parameter in the constructor:

WireframeSentry(IDirect3DDevice9* device, bool reallyEnable=true)

Clearly this solution doesn't scale, and it doesn't attack the problem at hand - how to conditionally create objects *and* reap the fruit of the destructor-on-scope-exit that the compiler guarantees for local objects.

Solution:

Enter predicated construction. Our example will be superceded by:

bool renderInWireframe = ...;
BOOST_PREDICATED_ANONYMOUS_CONSTRUCTOR(renderInWireframe, WireframeSentry, (device));


If renderInWireframe is true then an unnamed object will be created and destroyed on scope exit. Otherwise nothing will happen (save for an 'if').

Link to the code @ Boost vault

1 comment:

Stefan said...

I've been pointed to that the Boost.Optional library implements a feature with similar semantics but different purpose. The good thing about boost::optional is that it doesn't require macros to operate - a relief, really.