Making use of RAII requires to create a class to benefit from the mechanism that automatically calls the destructor of automatic variables when exiting a scope.
However, there are some cases when writing a new class in order to "release" something or unset something seems to be too much work.
For example, if you have a method that sets the value of a field only for the duration of the call, then you have to manually unset it if the call returns or throws, and it wouldn't be practical and intuitive to write a class that would just automatically unset that field and that would only be usable for this particular case.
So I thought about writing some kind of all-purpose class that can make use of RAII for all cases for which it is not really worth making a class.
The idea is that you provide an object instance, a method pointer to be called on construction, and a method pointer to be called on destruction :
template< class T >
class guard
{
private:
T * const m_pInstance;
void (T::* const m_fnInitialize)();
void (T::* const m_fnFinalize)() throw();
public:
guard( T * pInstance, void (T::* fnInitialize)(), void (T::* fnFinalize)() throw() ) :
m_pInstance ( pInstance ),
m_fnInitialize ( fnInitialize ),
m_fnFinalize ( fnFinalize )
{
(m_pInstance->*m_fnInitialize)();
}
~guard() throw()
{
(m_pInstance->*m_fnFinalize)();
}
};
Which can the be used like this :
class some_class
{
private:
int m_iField;
public:
some_class() : m_iField( 0 )
{
}
void set()
{
std::cout << "set()" << std::endl;
m_iField = 1;
}
void unset() throw()
{
std::cout << "unset()" << std::endl;
m_iField = 0;
}
};
int main( int argc, char ** argv )
{
some_class oObj;
{
core::guard< some_class > oGuard( & oObj, & some_class::set, & some_class::unset );
}
system( "pause" );
return 0;
}
It seels to me like it could be handy. But do you see any reason why this would be a bad practice ?
Also the way I designed this is not entirely "generic" as it poses some constraints : the initialization and finalization methods are non-const and the finalization method may no throw. Are there ways to making this more flexible ?
Thank you.