Ich habe eine Template-Klasse mit einer Spezialisierung, die in einer anderen Datei definiert ist. Daher ist es möglich, zwei Versionen derselben Klasse zu generieren: Einmal durch Ersetzen des Template-Parameters und einmal durch Verwenden der Spezialisierung. Mein derzeitiges Verständnis ist, dass dies dazu führen kann, dass zwei Instanzen des gleichen Typs unterschiedliche Größen im Speicher haben, was zu Segmentierungsfehlern führt.So finden Sie doppelte Definitionen aus Vorlagenspezialisierungen?
habe ich ein minimales Beispiel und der folgende Code ist die Frage zu veranschaulichen:
eine Template-Klasse erstellen:
// - templateexample.h ---------------
#ifndef TEMPLATEEXAMPLE_H
#define TEMPLATEEXAMPLE_H
template<typename T> class Example
{
public:
Example(){}
int doWork() {return 42;}
};
#endif
// -----------------------------------
Template Spezialisierung in einer anderen Datei:
// - templatespecialization.h --------
#ifndef TEMPLATESPECIALIZATION_H
#define TEMPLATESPECIALIZATION_H
#include "templateexample.h"
template<> class Example<int>
{
public:
Example() : a(0), b(1), c(2), d(3) {}
int doWork() {return a+b+c+d;}
private:
int a; //<== the specialized object will be larger in memory
int b;
int c;
int d;
};
#endif
// --------------------------------
Haben Sie einen Klasse, die nur die Vorlagenklassendefinition enthält, aber sollte die Spezialisierung enthalten.
// - a.h --------------------------
#ifndef A_H
#define A_H
#include "templateexample.h"
class A
{
public:
Example<int> returnSmallExample();
};
#endif
// - a.cpp ------------------------
#include "a.h"
Example<int> A::returnSmallExample() {return Example<int>();}
// --------------------------------
Die Hauptklasse jetzt kennt zwei Versionen von Example<int>
derjenige von A und das von der templatespecialization.h.
// - main.cpp ---------------------
#include <iostream>
#include "a.h"
#include "templatespecialization.h"
int main()
{
A a;
Example<int> test = a.returnSmallExample();
std::cout<<test.doWork()<<std::endl;
}
// --------------------------------
Bitte beachten Sie, dass dieses Problem nur auftreten, wenn separat Klasse A Kompilieren dieses Beispiel aus ideone Ausgängen 6, während unter Verwendung von separaten Dateien in einer Segmentierung Fauls führen kann, oder Ausgang 42 (https://ideone.com/3RTzlC). Auf meinem Rechner erstellt das Beispiel erfolgreich und Ausgänge 2013265920:
In der Serienversion des obigen Beispiel ist alles in eine gemeinsam genutzte Bibliothek, die von Haupt verwendet wird.
Frage 1: Warum erkennt der Linker dieses Problem nicht? Dies sollte leicht zu erkennen sein, indem man die Größe von Objekten vergleicht.
Frage 2: Gibt es eine Möglichkeit, die Objektdateien oder die gemeinsam genutzte Bibliothek zu untersuchen, um mehrere Implementierungen desselben Typs wie im obigen Beispiel zu erkennen?
Bearbeiten: Bitte beachten Sie: Der obige Code ist ein minimales Beispiel, um das Problem zu erklären. Der Grund für die Situation ist, dass die Vorlagenklasse aus einer Bibliothek stammt und ich die Dateien aus dieser Bibliothek nicht bearbeiten kann. Schließlich wird das Ganze überall in der ausführbaren Datei verwendet und jetzt muss ich herausfinden, ob das obige Problem auftritt.
Edit: Code oben kann wie folgt zusammengefasst werden:
#!/bin/bash
g++ -g -c a.cpp
g++ -g -c main.cpp
g++ -o test a.o main.o
Ihr Code ist grundsätzlich schlecht strukturiert. Jedes Mal, wenn Sie eine Vorlage instanziieren, müssen * alle * Spezialisierungen sichtbar sein. Fügen Sie einige Teilspezialisierungen nicht in eine separate Header-Datei ein. Behalte alles in einer Kopfzeile. –
@KerrekSB dies ist nicht unter meiner Kontrolle. Der Vorlagenkopf stammt aus einer Bibliothek, die ich nicht bearbeiten kann. – Beginner
Sie können jedoch einen eigenen Header schreiben, der die Vorlage enthält und dann die Spezialisierung definiert. Verwenden Sie das im gesamten Programm konsistent und fügen Sie niemals direkt den Header der Bibliothek ein. – Wyzard