C++ statische Template-Variablen Spezialisierung

Gast #3568975
Hallo zusammen,

ich möchte in einer Template-Klasse einen statischen String anlegen, 
welches den Namen des Template-Typs speichert. Der Name soll über 
typeid(T).name() ermittelt werden:
1
template<class T>
2
class C {
3
    static std::string ownTypename;
4
};
5

6
template<class T>
7
std::string C<T>::ownTypename = typeid(T).name();

Soweit so gut. Da der gcc (4.6.3) dabei etwas seltsame Namen prozutiert 
(mit _Z... am Anfang), möchte ich zum leichteren Debuggen für die 
üblichen Datentypen eine Spezialisierung erstellen:
1
template<>
2
std::string C<int>::ownTypename = "int";

Und das funktioniert nicht so wie erwartet.

Wenn ich die Definition von C<int>::ownTypename in den Header packe, 
meckert der Linker, dass es mehrmals definiert wurde, was ja auch 
nachvollziehbar ist. Wenn ich es in eine .cpp Datei packe, passiert 
etwas, was ich nicht verstehe.

Das Projekt ist noch im Aufbau und ich habe neben den verschiedenen 
Klassen eine main.cpp, wo in main() verschiedene Teile gestestet werden. 
Falls ich die Definition von C<int>::ownTypename in die main.cpp packe, 
compiliert das Projekt und gibt auch den richtigen spezialisierten 
Typstring aus. Falls ich die Definition aber in eine andere .cpp Datei 
lege, sagt der Linker es wäre bereits schon definiert (ja, ich habe die 
Definition aus main.cpp wieder gelöscht). Was das ganze noch seltsamer 
macht, ist dass der Fehler angeblich in
1
/usr/include/c++/4.6/x86_64-linux-gnu/bits/gthr-default.h:241: first defined here
passiert. Das kann ich absolut nicht nachvollziehen, da meines Wissens 
nach die einzelnen .cpp Dateien getrennt kompliert und am Ende 
gleichwertig zusammengelinkt werden.

Noch kurioser ist, dass ich das Projekt ohne die main (aber mit 
Definitionen von ownTypename) zu einer Bibliothek linken kann. Sobald 
ich diese benutze, werden die Spezialisierungen ignoriert. Wenn ich nun 
jedoch versuche, die Definitionen in die main.cpp des anderen Projektes, 
welches die Bibliothek vom ersten Projekt linkt, hinzuzufügen, sagt der 
Linker, die Definitionen gäbe es schon ("multiple definition").

Habe ich da etwas falsch gemacht, oder ist das ein Bug vom gcc, oder 
...?
Gast
So müsste es gehen:

foo.h:
1
#include <string>
2
#include <typeinfo>
3

4
template<class T>
5
struct C {
6
        static std::string classname;
7
};
8

9
template<class T>
10
std::string C<T>::classname = typeid(T).name();
11

12
extern template std::string C<int>::classname;
foo.cpp:
1
#include "foo.h"
2

3
template<>
4
std::string C<int>::classname = "int";
D.h., C<int>::classname wird in foo.h als explizite 
Template-Instantiierung deklariert, aber nicht definiert. Dadurch weiß 
der Compiler, dass die Definition der Instanz anderswo existiert und 
instantiiert diese spezielle Ausgabe des Templates nicht mehr. Die 
explizite Instanz definieren wir dann in foo.cpp.
Gast
Bin hier nicht sattelfest. Ich hatte mal folgende Theorie:

template ohne <> leitet man eine Instantiierung ein, template<> leitet 
eine Spezialisierung ein.

Instantiierung: Das Stanzwerkzeug (template) wird benutzt, um ein 
konkretes "Ding" zu generieren. In unserem Fall die konkrete Deklaration 
einer konkreten Variablen.

Spezialisierung: Eine alternatives Stanzwerkzeug (template) für einen 
eingeschränkten Verwendungszweck wird festgelegt.

Diese Theorie versagt aber, denn dann müsste in foo.cpp template ohne <> 
verwendet werden. Das hat bei meinen Tests aber nicht funktioniert. Und 
so wie ich's oben vorschlage, wäre in foo.cpp wieder nur ein Template 
(wenn auch ein spezialisiertes), aber nichts, was eine Instantiierung 
erzwingt.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 12 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.