5

Ich schrieb irgendwann Code, der eine statische Tabelle/ein Array zur Kompilierzeit für einige Template-Metaprogrammierung erzeugte (die Idee ist, dass C-Style-Strings zur Kompilierzeit erstellt werden können (sie sind nur char Arrays)). Die Idee und der Code basiert weg David Lin ‚s answer:Statische Tabellengenerierung funktioniert mit GCC, aber nicht mit Klängen; wird geklingelt?

#include <iostream> 

const int ARRAY_SIZE = 5; 

template <int N, int I=N-1> 
class Table : public Table<N, I-1> 
{ 
public: 
    static const int dummy; 
}; 

template <int N> 
class Table<N, 0> 
{ 
public: 
    static const int dummy; 
    static int array[N]; 
}; 

template <int N, int I> 
const int Table<N, I>::dummy = Table<N, 0>::array[I] = I*I + 0*Table<N, I-1>::dummy; 

template <int N> 
int Table<N, 0>::array[N]; 

template class Table<ARRAY_SIZE>; 

int main(int, char**) 
{ 
    const int *compilerFilledArray = Table<ARRAY_SIZE>::array; 
    for (int i=0; i < ARRAY_SIZE; ++i) 
     std::cout<<compilerFilledArray[i]<<std::endl; 
} 

Kompilieren Sie diesen Code mit GCC 4.9.2 Werke:

Clang 3.5 beschwert, aber:

$ clang++ -Wall -pedantic b.cpp 
Undefined symbols for architecture x86_64: 
    "Table<5, 0>::dummy", referenced from: 
     ___cxx_global_var_init in b-b8a447.o 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

dummy und array werden beide Definitionen außerhalb der Table Klasse angegeben (wo sie deklariert sind). Soweit ich das beurteilen kann, sollte dies die Linker-Anforderungen erfüllen.

Ist das ein Bug mit Klängen?

Antwort

6

Alle statischen Datenelemente für primäre und partielle Spezialisierungen müssen separat definiert werden.

template <int N, int I> 
const int Table<N, I>::dummy = …; 

Die hier definierten einzige Sache ist Table<N, I>::dummy - die primäre Spezialisierungen statisches Datenelement. [Temp.class.spec.mfunc]/1 :

Klasse Schablonen-Teil Spezialisierung Elemente, die in einer Weise verwendet werden, die eine Definition definiert sind, erfordert; die Definitionen von Mitglieder der primären Vorlage werden nie als Definitionen für Mitglieder einer Klassenvorlage teilweise Spezialisierung verwendet.

Dies bedeutet auch, dass GCC hier falsch ist. Das ist ein Fehler.
Eitherway,

template <int N> 
const int Table<N, 0>::dummy = 0; 

Fein Sollte kompilieren hinzufügen.


1) Insbesondere in dem gleichen Abschnitt wie das Zitat oben:

Die Templat-Parameterliste eines Mitglieds einer Klasse Vorlage Teil Spezialisierung wird die Vorlage Parameterliste Übereinstimmen von die Klasse Vorlage teilweise Spezialisierung.
Die Template-Argumentenliste eines Members einer partiellen Spezialisierung einer Klassenvorlage soll mit der Template-Argumentliste der partiellen Spezialisierung der Klassenvorlage übereinstimmen.

Das heißt, die Argumentlisten zur Definition der Teil Spezialisierung und sein Element verwendet müssen gleich sein. Ansonsten wird dieses Mitglied nie definiert.

+0

Ah, das macht Sinn! Es ist eine Schande, dass ich nur einmal abstimmen kann. Außerdem freue ich mich auf die Standardzitate, wenn Sie sie bekommen. – Cornstalks

+0

@Cornstalks Sie sind da :) – Columbo

+0

Können Sie bitte einen Link zum GCC-Fehlerbericht hinzufügen? –