Consider the following C API:
void BeginTransaction(State *s);
void AddToTransaction(State *s, Object *value);
void CommitTransaction(State *s);
void Foo(State *s, Object *value)
{
BeginTransaction(s);
AddToTransaction(s, value);
CommitTransaction(s);
}
I created a C++ class to wrap this API:
class StateTransaction
{
public:
StateTransaction(State *s) : state_(s)
{
BeginTransaction(state_);
}
StateTransaction(const StateTransaction &st) = delete;
void Add(Object *value)
{
AddToTransaction(state_, value);
}
~StateTransaction()
{
CommitTransaction(state_);
}
private:
State *state_;
}
void Foo(State *s, Object *value)
{
StateTransaction st(s);
st.Add(value);
// When st goes out of scope, the transaction automatically gets committed
}
Assuming that none of the functions can fail, is this a good use case for RAII? My main problem with it right now is that in order to force the transaction to be committed before some other code, I need to put the object in a new scope:
void Foo(State *s, Object *value)
{
{
StateTransaction st(s);
st.Add(value1);
}
// Code which relies on transaction being completed
}
And of course, there's the danger that someone will come along and delete the braces because they look useless. That could be fixed with a comment like /* DO NOT DELETE BRACES */
, but at that point it seems safer to just use the C API.
So, is the RAII wrapper a good idea? Or should I stick to the C style?