6 Stimmen

Was sind die Regeln für die Instantiierung von Vorlagenarten (Klasse/Funktion), wenn man eine Adresse benötigt?

Bei der Beantwortung dieser Frage bin ich auf diesen Unterschied im Verhalten hinsichtlich der Template-Instantiierung gestoßen.

Zunächst gibt es ein Funktions-Template:

template  void my_callback(void* data) { … }

Jetzt wird etwas benötigt, was die Adresse davon erfordert - speziell ein void*, also ist der offensichtliche Ansatz:

bar(reinterpret_cast(&my_callback));

Allerdings schlägt dies mit Compiler-Versionen vor gcc 4.5 fehl, mit einem "not-enough context..." Fehler. In Ordnung - also wird die Lösung sein, zuerst zu "casten" - was die Instantiierung erzwingt, also:

void (*callback)(void*) = my_callback;
bar(reinterpret_cast(callback));

Dies funktioniert gut.

Jetzt das zweite Szenario, anstatt eine freie Funktion zu sein, ist es ein statisches Element einer Klassen-Vorlage, also:

template 
struct foo
{
  static void my_callback(void* data) {
    T& x = *static_cast(data);
    std:: cout << "Aufruf[T] mit " << x << std::endl;
  }
};

Jetzt funktioniert das originale reinterpret_cast gut.

bar(reinterpret_cast(&foo::my_callback));

Also meine Frage ist - warum dieser scheinbare Unterschied im Verhalten?

2voto

Luc Danton Punkte 34153

Von n3290, 14.7.1 Implizite Instanziierung [temp.inst]

2 Sofern eine Funktionstemplatespezialisierung nicht explizit instanziiert oder explizit spezialisiert wurde, wird die Funktionstemplatespezialisierung implizit instanziiert, wenn die Spezialisierung in einem Kontext referenziert wird, der eine Funktionsdefinition erfordert.

Es gelten ähnliche Regeln in Absatz 1 für Klassentemplatespezialisierungen. Beachten Sie, dass der Standard von Spezialisierung spricht, da eine Spezialisierung implizit deklariert wird, wenn ein Template verwendet wird und keine benutzerdefinierte Spezialisierung vorhanden ist, zumindest für Funktionstemplates (Absatz 8).

Zusammen mit Absatz 10:

10 Ein Implementierung darf keine Funktionstemplates, Klassentemplates, nicht virtuelle Klassenmemberfunktionen, Klassenmembers oder statische Datamembers eines Klassentemplates implizit instanziieren, die keine Instantiierung erfordern.

Meiner Meinung nach ist die Faustregel: Sobald ein Objekt/Klassenmember/Funktion benötigt wird oder um das Programm anderweitig zu aktivieren (informell gesprochen), wird das Template implizit instanziiert, aber nicht früher. Dies umfasst auch das Adressieren einer Funktion.

Hinsichtlich der von Ihnen verlinkten Frage können einige Verwendungen von reinterpret_cast das Programm nicht konform machen, zu diesem Zeitpunkt ist es irrelevant, Instanziierungen zu erwähnen - ich lade Sie ein, meine Antwort dort zu sehen /schamlos.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X