13

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?

Horstling
  • 2,131
  • 12
  • 14

1 Answers1

12

Suppose the inline function is in a header included in two different translation units, and the value of the counter happens to be at a different value in each.

Then you have two definitions of the inline function with different names for the variable. That's an ODR violation - you have to use the same sequence of tokens for every definition.

(Although in practice I'd be very surprised if it caused any problem.)

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
  • I just came to the same conclusion, took me a while to realize that it's about the definition of the function itself. But ofc this makes sense, even if it is just about a diffent variable name. I guess one can only hope that this doesn't cause any problems... maybe the LINE macro would be a better choice here? – Horstling May 17 '16 at 06:48
  • Yes, unless you want to declare more than one of those things on one line. (Or you're messing with `#line`.) – Alan Stokes May 17 '16 at 07:14