2010-02-26 5 views
13
class A 
{ 
}; 

template <typename A, int S> 
class B 
{ 
public: 
     static int a[S]; 

     B() 
     { 
       a[0] = 0; 
     } 
}; 

template<> int B<A, 1>::a[1]; 

int main() 
{ 
     B<A, 1> t; 
     t; 
} 

Compila sotto GCC 4.1, ma non collega:inizializzazione membro statico per la classe template specializzata

static.cpp:(.text._ZN1BI1ALi1EEC1Ev[B<A, 1>::B()]+0x5): undefined reference to `B<A, 1>::a' 

preferirei mantenere l'inizializzazione specializzata se è possibile, dal momento che l'array contiene alcuni dati specifici al tipo

+1

Non B :: a hanno solo 1 elemento? Quindi, facendo riferimento a B :: a [1], non stai indicizzando oltre i limiti dell'array? – Dathan

+0

Non vedo 'typename A' doing * anything * in there. –

risposta

1

È necessario assegnare effettivamente un valore ad esso.

+1

Non dovrebbe essere il modello <> int B :: a = {0}? – Dathan

+0

@Dathan: perché? Il tuo codice è 'errore: dichiarazione in conflitto 'int B :: a''. – kennytm

+1

@Dathan, quella dichiarazione sarebbe specializzata in un membro intero, non in un array. –

0

Non si collega perché non si definisce un valore per il membro statico.

template<> int B<A, 1>::a[] = { 0 }; 

Edit:

Btw: io preferisco sempre usare boost :: matrice invece di C-tipi nativi:

class A { }; 

template <typename A, std::size_t S> 
class B 
{ 
public: 
    static boost::array<int, S> a; 

    B() { a[0] = 0; } 
}; 

template<> boost::array<int, 1> B<A, 1>::a = { }; 

int main() 
{ 
    B<A, 1> t; 
    cout << t.a[0] << endl; 
} 
31

Per specializzazioni membro statiche, se don Inizializza il membro, viene preso come una specializzazione dichiarazione, che dice semplicemente "Oh, non istanziare il membro dal modello principale, perché c'è uno speciale definizione definita da qualche altra parte ". Va detto che la definizione dovrebbe apparire in un file .cpp (altrimenti, si guadagnerà il contrario: più definizioni), e la dichiarazione senza inizializzatore dovrebbe essere ancora posizionata nel file di intestazione.

Ora la sintassi corretta è infatti il ​​seguente, e dovrebbe non apparire in un file di intestazione, ma in un file .cpp

template<> int B<A, 1>::a[1] = { }; 

Il seguente dovrebbe comunque apparire in un file di intestazione:

template<> int B<A, 1>::a[1]; 

Questo servirà come specializzazione dichiarazione.


Da questo, ne consegue che non si può specializzare un membro che ha solo un costruttore di default e non è copiabile, perché si avrebbe bisogno questa sintassi:

// needs a copy constructor! 
template<> Type Class<Arguments>::member = Type(); 

C++ 0x correzioni questo:

// doesn't anymore need a copy constructor 
template<> Type Class<Arguments>::member{}; 

Per la gente Standardese tra di noi, qui ci sono le citazioni:

01.235.164,106174 millions

14.7.3/6:

If a template, a member template or the member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.

14.7.3/15:

An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. [Note: there is no syntax for the definition of a static data member of a template that requires default initialization.

template<> X Q<int>::x; 

This is a declaration regardless of whether X can be default initialized (8.5). ]

3.2/3:

Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required.

3.2/5:

There can be more than one definition of a class type (clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (clause 14), non-static function template (14.5.5), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.4) in a program [...]

La restrizione di questo "per il quale alcuni parametri del modello non sono specificati" significa che stiamo permesso di effettuare le seguenti operazioni, collocandolo in un'intestazione (quindi, eventualmente con più definizioni di questa specializzazione):

template<> template<typename T> 
Type OuterClass<int>::InnerClass<T>::StaticMember = 0; 

Nel tuo caso, hai tutti i parametri specificati, che non sono coperti dalla regola di una definizione per consentire più definizioni.