Inlining-Template-Spezialisierung

Lesezeit: 3 Minuten

Wenn ich einen Header foo.h habe, den ich in mein gesamtes Projekt einfüge, scheint er gut zu funktionieren, wenn er nur Folgendes enthält:

template<typename T>
void foo(const T param) {
    cout << param << endl;
}

Aber ich erhalte One-Definition-Rule-Fehler (ODR), wenn ich foo.h eine Spezialisierung hinzufüge:

template<>
void foo(const bool param) {
    cout << param << endl;
}

Offensichtlich kann ich das lösen, indem ich inline‘ing die Spezialisierung. Meine Frage ist, warum muss ich das? Wenn die Vorlage ODR nicht verletzt, warum eine Spezialisierung?

  • Eine Spezialisierung einer Template-Funktion ist eine Definition, wenn der Körper definiert ist.

    – Richard Hodges

    23. August 2018 um 13:52 Uhr


  • verwandt/dupe: stackoverflow.com/questions/10535667/…

    – NathanOliver

    23. August 2018 um 13:53 Uhr

  • @NathanOliver Ja, ich habe mir das angesehen … es geht nicht um Spezialisierung. Ich hatte wirklich nur auf etwas Offizielles gehofft, das besagte, dass ich es tun musste inline. Sieht aus, als hätte StoryTeller mich erwischt.

    – Jonathan Mei

    23. August 2018 um 13:59 Uhr

  • @JonathanMee Tut es nicht? Was ist in der Mitte der Antwort unten tpl.h (entnommen aus der expliziten Spezialisierung): das hat genau den gleichen Codeblock?

    – NathanOliver

    23. August 2018 um 13:59 Uhr

  • @ NathanOliver Heh … na schau dir das an. Ich habe mir nur die Frage angesehen: / Ich hätte nichts dagegen, dies zu täuschen. Da ist es dort drüben gut beantwortet. Was denkst du?

    – Jonathan Mei

    23. August 2018 um 14:00 Uhr


Eine explizite Spezialisierung ist nicht implizit inline. Es muss explizit inline gemacht werden.

[temp.expl.spec]/12

Eine explizite Spezialisierung einer Funktions- oder Variablenvorlage ist nur dann inline, wenn sie mit dem Inline-Bezeichner deklariert oder als gelöscht definiert ist, und unabhängig davon, ob ihre Funktions- oder Variablenvorlage inline ist. [ Example:

template<class T> void f(T) { /* ... */ }
template<class T> inline T g(T) { /* ... */ }

template<> inline void f<>(int) { /* ... */ }   // OK: inline
template<> int g<>(int) { /* ... */ }           // OK: not inline

 — end example ]

Also musst du es tun, weil die Norm sagt, dass du es tun musst.

Der Grund, warum Vorlagen von ODR ausgenommen sind, ist einfach, dass es keine andere Wahl gibt.

Eine Vorlage ist aus der Sicht des Compilers kein “greifbares Endprodukt”. Die Implementierung von Vorlagen muss mitgeführt werden, damit sie bei Verwendung zu kompilierbarem Code erweitert werden können. Folglich muss es in einer Header-Datei liegen, und doppelte Definitionen von verschiedenen Kompilierungseinheiten sind konsequent und unvermeidbar. Da dies unvermeidbar ist, geht die Norm einen Kompromiss ein, um sie von ODR auszunehmen.

Eine Funktion ist ein Endprodukt, das leicht in Zielcode kompiliert werden kann, daher hassen es Compiler, potenziell widersprüchliche Definitionen zu sehen, selbst wenn es durchaus möglich ist, die Codes zu vergleichen und fortzufahren, wenn die Codes identisch sind. Die Compiler entscheiden jedoch, dass sie viel zu faul sind, um eine solche zusätzliche Überprüfung durchzuführen, und daher verbietet der Standard mehrere Definitionen.

Nun, ein explizit/vollständig Spezialisierung einer Template-Funktion ist de facto eine Funktion, keine Vorlage – da alle fehlenden Teile ausgefüllt wurden und es nicht mehr nötig ist, die Definition der spezialisierten Funktion mit sich herumzutragen. Im Gegensatz dazu ist A teilweise Spezialisierung ist de facto eine Vorlage, da deren Implementierung noch während der Kompilierung herumgetragen werden muss. Daher genießen partielle Template-Spezialisierungen die von Templates geerbte Ausnahme, während explizite/vollständige Spezialisierungen dies nicht tun.

  • Template sind nicht von ODR ausgenommen, Token sollte identisch sein, resultierende Instanziierung sollte sich identisch “verhalten” (visible function for ADL, …). Es erfordert einfach nicht inline Stichwort.

    – Jarod42

    23. August 2018 um 14:31 Uhr

1018950cookie-checkInlining-Template-Spezialisierung

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy