In this presentation intorno alle 00:19:00, Andrei Alexandrescu spiega l'implementazione della sua macro SCOPE_EXIT
. Egli crea un oggetto ScopeGuard
sullo stack che esegue una lambda sulla distruzione:Come può __COUNTER__ causare una violazione ODR qui?
#define ANONYMOUS_VARIABLE(str) \
CONCATENATE(str, __COUNTER__)
namespace detail {
enum class ScopeGuardOnExit {};
template <typename Fun>
ScopeGuard<Fun>
operator+(ScopeGuardOnExit, Fun&& fn) {
return ScopeGuard<Fun>(std::forward<Fun>(fn));
}
}
#define SCOPE_EXIT \
auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
= ::detail::ScopeGuardOnExit() + [&]()
Finora, così ben noto (si afferma anche nei suoi diapositive che si tratta di un vecchio cappello). L'utilizzo è simile al seguente:
void foo()
{
SCOPE_EXIT{ printf("foo exits"); };
}
Ma a 01:04:00, Chandler Carruth sostiene che questo uso del __COUNTER__
macro per creare un nome di "anonimo" causerebbe una violazione di ODR quando viene utilizzato in una funzione inline. Può essere vero? La macro viene utilizzata solo per creare un nome di variabile locale, non un nome di tipo o qualcosa del genere, quindi come ciò potrebbe causare una violazione ODR?
ho appena venuto alla stessa conclusione, mi ha portato un po 'per capire che si tratta di circa la definizione della funzione stessa. Ma questo ha senso, anche se si tratta solo di un nome variabile diverso. Immagino che si possa solo sperare che questo non causi problemi ... forse la macro LINEA sarebbe una scelta migliore qui? – Horstling
Sì, a meno che non si desideri dichiarare più di una di queste cose su un'unica riga. (Oppure stai scherzando con '# line'.) –