2016-05-17 11 views
7

W this presentation około 00:19:00, Andrei Alexandrescu wyjaśnia implementację swojego makra SCOPE_EXIT. Tworzy ScopeGuard obiekt na stosie, który wykonuje lambda na zniszczenia:W jaki sposób __COUNTER__ może spowodować naruszenie ODR?

#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() + [&]() 

Tak daleko, tak dobrze znane (nawet stwierdza w swojej zjeżdżalniami, że jest to stary kapelusz). Wykorzystanie wygląda następująco:

void foo() 
{ 
    SCOPE_EXIT{ printf("foo exits"); }; 
} 

Ale 01:04:00 Chandler Carruth twierdzi, że korzystanie z __COUNTER__ makro do stworzenia „anonimowy” nazwę spowodowałoby naruszenie zasad ODR użyte w funkcji inline. Czy to może być prawda? Makro służy tylko do tworzenia nazwy zmiennej lokalnej, a nie nazwy typu lub czegoś, więc w jaki sposób może to spowodować naruszenie ODR?

Odpowiedz

8

Załóżmy, że funkcja inline znajduje się w nagłówku zawartym w dwóch różnych jednostkach tłumaczeniowych, a wartość licznika ma inną wartość w każdej z nich.

Następnie masz dwie definicje funkcji inline z różnymi nazwami dla zmiennej. Jest to naruszenie ODR - musisz użyć tej samej sekwencji żetonów dla każdej definicji.

(choć w praktyce Byłbym bardzo zaskoczony, gdyby to spowodowało żadnego problemu.)

+0

Właśnie doszedł do tego samego wniosku, zajęło mi trochę czasu, aby uświadomić sobie, że to chodzi o definicję samej funkcji. Ale ofc ma sens, nawet jeśli chodzi tylko o inną zmienną nazwę. Sądzę, że można mieć tylko nadzieję, że to nie spowoduje żadnych problemów ... może makro LINE byłoby lepszym wyborem tutaj? – Horstling

+0

Tak, chyba że chcesz zadeklarować więcej niż jedną z tych rzeczy w jednym wierszu. (Albo mieszkasz z '# line'.) –

Powiązane problemy