Considera la seguente API C:
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);
}
Ho creato una classe C ++ per racchiudere questa 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
}
Supponendo che nessuna delle funzioni possa fallire, è un buon uso di RAII? Il mio problema principale in questo momento è che per forzare la transazione a essere commessa prima di qualche altro codice, ho bisogno di mettere l'oggetto in un nuovo ambito:
void Foo(State *s, Object *value)
{
{
StateTransaction st(s);
st.Add(value1);
}
// Code which relies on transaction being completed
}
E naturalmente, c'è il pericolo che qualcuno venga e cancelli le parentesi perché sembrano inutili. Potrebbe essere corretto con un commento come /* DO NOT DELETE BRACES */
, ma a quel punto sembra più sicuro usare solo l'API C.
Quindi, il wrapper RAII è una buona idea? O dovrei attenermi allo stile C?