Non mi piace davvero rispondere alla mia domanda qui, soprattutto perché ho capito che ho fatto la domanda sbagliata. Ero troppo concentrato sui termini e sulle abitudini di OO, ma la realtà è che quello che volevo era un prodedure , non una classe o qualcosa che potesse effettivamente memorizzare uno stato. Ci scusiamo per questo.
Ecco la mia soluzione (non del tutto funzionante) (soluzione migliorata di seguito):
Ho ricordato che ci sono macro che gestiscono "blocchi atomici" cancellando un flag di abilitazione dell'interrupt quando viene inserito il blocco e ripristinandolo dopo che il blocco è stato eseguito. Ho dato un'occhiata a quelli e sono fondamentalmente solo un ciclo for
.
Insieme a una definizione di struttura anonima nell'inizializzazione del ciclo for ( link ) questa soluzione è diventata una soluzione che funziona per me:
#include <iostream>
struct Settings
{
Settings(int v_) : v(v_) {}
int v;
};
//https://stackoverflow.com/a/11255852
#define useHardwareWith(settings) \
acquireHardware(settings); \
for( \
struct \
{ \
bool done() \
{ \
return done_; \
} \
bool run() \
{ \
releaseHardware(); \
done_ = true; \
} \
bool done_; \
} magic = {false}; !magic.done() ; magic.run())
void acquireHardware(const Settings& settings)
{
std::cout << "acquire(" << settings.v << ")\n";
}
void releaseHardware()
{
std::cout << "release()\n";
}
int main()
{
Settings settings(1);
useHardwareWith(settings)
{
std::cout << "Doing important hardware stuff\n";
}
}
Output:
acquire(1)
Doing important hardware stuff
release()
Demo online: link
La macro for
non può essere memorizzata, quindi non è non consentire l'archiviazione non locale , ma semplicemente fare qualcosa in un ordine specifico.
È meglio
La soluzione di cui sopra ha un grosso problema: release()
non viene chiamato quando break
o return
viene chiamato nel ciclo, perché release()
è nella parte "increment" e non in un distruttore. Sfortunatamente, un distruttore per l'anonimo non può essere definito. Così ho aggiunto una struttura interna con nome per farlo:
#include <iostream>
struct Settings
{
Settings(int v_) : v(v_) {}
int v;
};
//https://stackoverflow.com/a/11255852
#define useHardwareWith(settings) \
acquireHardware(settings); \
for( \
struct \
{ \
struct inner \
{ \
inner() : done_(false) \
{ \
} \
~inner() \
{ \
releaseHardware(); \
} \
bool done_; \
}; \
bool done() const \
{ \
return inner_.done_; \
} \
bool run() \
{ \
inner_.done_ = true; \
} \
inner inner_; \
} magic; !magic.done() ; magic.run())
void acquireHardware(const Settings& settings)
{
std::cout << "acquire(" << settings.v << ")\n";
}
void releaseHardware()
{
std::cout << "release()\n";
}
void doHardwareStuff(const Settings& settings)
{
useHardwareWith(settings)
{
if (settings.v == 0)
{
std::cout << "side-exit\n";
return;
}
std::cout << "Doing important hardware stuff\n";
}
}
int main()
{
Settings settings(0);
doHardwareStuff(settings);
doHardwareStuff(Settings(1));
}
Demo online: link