In this presentation at around 00:19:00, Andrei Alexandrescu explains the implementation of his SCOPE_EXIT
macro. He creates a ScopeGuard
object on the stack that executes a lambda on destruction:
#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() + [&]()
So far, so well known (he even states in his slides that this is an old hat). The usage looks like this:
void foo()
{
SCOPE_EXIT{ printf("foo exits"); };
}
But at 01:04:00, Chandler Carruth claims that this usage of the __COUNTER__
macro to create an "anonymous" name would cause an ODR violation when used in an inline function. Can this be true? The macro is only used to create a local variable name, not a type name or something, so how could this cause an ODR violation?