2016-05-17 5 views
7

In this presentation um 00:19:00, erklärt Andrei Alexandrescu die Umsetzung seiner SCOPE_EXIT Makro. Er schafft ein ScopeGuard Objekt auf dem Stapel, der eine Lambda auf Zerstörung führt:Wie kann __COUNTER__ hier eine ODR-Verletzung verursachen?

#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 weit, so gut bekannt (er sagt sogar in seinen Dias, dass dies ein alter Hut). Die Verwendung wie folgt aussieht:

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

Aber 01.04.00, behauptet Chandler Carruth, dass diese Nutzung des __COUNTER__ Makro einen „anonymen“ namen eine ODR Verletzung zu schaffen, würde verursachen, wenn sie in einer Inline-Funktion verwendet. Kann das wahr sein? Das Makro wird nur verwendet, um einen lokalen Variablennamen zu erstellen, keinen Typnamen oder etwas Ähnliches. Wie könnte dies also zu einer ODR-Verletzung führen?

Antwort

8

Angenommen, die Inline-Funktion befindet sich in einem Header, der in zwei verschiedenen Übersetzungseinheiten enthalten ist, und der Wert des Zählers ist in jedem Fall unterschiedlich.

Dann haben Sie zwei Definitionen der Inline-Funktion mit unterschiedlichen Namen für die Variable. Das ist eine ODR-Verletzung - Sie müssen für jede Definition die gleiche Token-Sequenz verwenden.

(Obwohl in der Praxis wäre ich sehr überrascht, wenn es irgendein Problem verursacht.)

+0

Ich kam gerade zu dem gleichen Schluss, dauerte eine Weile zu erkennen, dass es um die Definition der Funktion selbst ist. Aber das macht Sinn, auch wenn es sich nur um einen variablen Namen handelt. Ich denke, man kann nur hoffen, dass dies keine Probleme verursacht ... vielleicht wäre das LINE-Makro hier eine bessere Wahl? – Horstling

+0

Ja, es sei denn, Sie möchten mehr als eines dieser Dinge in einer Zeile deklarieren. (Oder du verarschst mit '# line'.) –

Verwandte Themen