Dies kam gerade im Zusammenhang mit einer anderen Frage auf .
Anscheinend werden Mitgliedsfunktionen in Klassenvorlagen nur instanziiert, wenn sie ODR-verwendet werden. Könnte jemand erklären, was genau das bedeutet. Der Wikipedia-Artikel über One Definition Rule (ODR) erwähnt " ODR-Verwendung " nicht.
Der Standard definiert es jedoch als
Eine Variable, deren Name als potenziell ausgewerteter Ausdruck angezeigt wird, wird odr verwendet, es sei denn, es handelt sich um ein Objekt, das die Anforderungen für das Erscheinen in einem konstanten Ausdruck (5.19) erfüllt, und die Konvertierung von Wert zu Wert (4.1) wird sofort angewendet.
in [basic.def.odr].
Bearbeiten: Anscheinend ist dies der falsche Teil und der gesamte Absatz enthält mehrere Definitionen für verschiedene Dinge. Dies könnte für die Funktion der Klassenvorlagenmitglieder relevant sein:
Eine nicht überladene Funktion, deren Name als potenziell ausgewerteter Ausdruck oder Mitglied einer Reihe von Kandidatenfunktionen angezeigt wird, wird odr-verwendet, sofern es sich nicht um eine reine virtuelle Funktion handelt, wenn sie durch Überlastungsauflösung ausgewählt wird, wenn auf einen potenziell ausgewerteten Ausdruck verwiesen wird Funktion und ihr Name ist nicht explizit qualifiziert.
Ich verstehe jedoch nicht, wie diese Regel über mehrere Kompilierungseinheiten hinweg funktioniert. Werden alle Elementfunktionen instanziiert, wenn ich eine Klassenvorlage explizit instanziiere?
quelle
Antworten:
Es ist nur eine willkürliche Definition, die vom Standard verwendet wird, um anzugeben, wann Sie eine Definition für eine Entität angeben müssen (im Gegensatz zu nur einer Deklaration). Der Standard sagt nicht nur "verwendet", da dies je nach Kontext unterschiedlich interpretiert werden kann. Und manche ODR-Nutzung entspricht nicht wirklich dem, was man normalerweise mit "Nutzung" assoziieren würde; Beispielsweise wird eine virtuelle Funktion immer ODR-verwendet, es sei denn, sie ist rein, auch wenn sie an keiner Stelle im Programm aufgerufen wird.
Die vollständige Definition befindet sich in §3.2 , zweiter Absatz, obwohl dieser Verweise auf andere Abschnitte enthält, um die Definition zu vervollständigen.
In Bezug auf Vorlagen ist die Verwendung von ODR nur ein Teil der Frage. Der andere Teil ist die Instanziierung. §14.7 behandelt insbesondere, wann eine Vorlage instanziiert wird. Die beiden hängen jedoch zusammen: Während der Text in §14.7.1 (implizite Instanziierung) ziemlich lang ist, besteht das Grundprinzip darin, dass eine Vorlage nur dann instanziiert wird, wenn sie verwendet wird, und in diesem Zusammenhang bedeutet verwendet ODR-verwendet. Daher wird eine Elementfunktion einer Klassenvorlage nur instanziiert, wenn sie aufgerufen wird oder wenn sie virtuell ist und die Klasse selbst instanziiert wird. Der Standard selbst zählt an vielen Stellen darauf: die
std::list<>::sort
Verwendung<
der einzelnen Elemente, aber Sie können eine Liste über einen Elementtyp instanziieren, der nicht unterstützt wird<
, solange Sie ihn nicht aufrufensort
.quelle
Im Klartext bedeutet odr-used, dass etwas (Variable oder Funktion) in einem Kontext verwendet wird, in dem die Definition vorhanden sein muss.
z.B,
Beachten Sie, dass der obige Push_back in MSVC 2013 übergeben wurde. Dieses Verhalten entspricht nicht der Standardkonformität. Sowohl gcc 4.8.2 als auch clang 3.8.0 sind fehlgeschlagen. Die Fehlermeldung lautet: undefinierter Verweis auf `K :: g_x '
quelle
vi.push_back( F::g_x );
in c ++ odr-zu verwenden ?const int&
? Könnte das statische const-Element als r-Wert eingestuft werden?push_back
, natürlich wird es bestanden. Ist es nicht?operator+
.