2010-10-07 16 views
114
#ifndef __TEST__ 
#define __TEST__ 

namespace std 
{ 
    template<typename T> 
    class list; 
} 

template<typename T> 
void Pop(std::list<T> * l) 
{ 
    while(!l->empty()) 
     l->pop(); 
} 

#endif 

e utilizzato quella funzione nel mio principale. Ottengo errori Certo, so che ci sono più parametri di template per std::list (allocator, penso). Ma questo è oltre il punto. Devo conoscere la dichiarazione completa del template di una classe template per poterla inoltrare dichiararla?Come inoltrare la dichiarazione di una classe template nello spazio dei nomi std?

MODIFICA: Non stavo usando un puntatore prima - era un riferimento. Lo proverò con il puntatore.

+0

E nel caso di elenco, il secondo parametro è un parametro predefinito che è 'std :: allocator ' – nakiya

+2

uno potrebbe considerare una svista che il STL non contiene intestazioni di dichiarazione in avanti. D'altra parte, i suoi file sono così spesso inclusi che probabilmente non produrranno alcun beneficio sul tempo di compilazione ... –

+6

'__TEST__' è un identificatore riservato, [non utilizzarlo] (http://stackoverflow.com/domande/228.783/cosa-sono-le-regole-about-utilizzando-an-sottolineatura-in-ac-identifier). – GManNickG

risposta

116

Il problema non è che non è possibile inoltrare una classe modello. Sì, si ha bisogno di conoscere tutti i parametri di modello ei loro valori predefiniti per essere in grado di inoltrare-dichiararlo correttamente:

namespace std { 
    template<class T, class Allocator = std::allocator<T>> 
    class list; 
} 

Ma per fare anche una dichiarazione del genere in avanti nella namespace std è esplicitamente vietato dalla norma : la solo cosa che è possibile inserire in std è un modello specializzazione, comunemente std::less su un tipo definito dall'utente. Qualcun altro può citare il testo pertinente, se necessario.

Solo #include <list> e non preoccuparti.

Oh, per inciso, qualsiasi nome che contenga caratteri di sottolineatura doppio è riservato all'implementazione, quindi è necessario utilizzare qualcosa come TEST_H anziché __TEST__. Non genererà un avviso o un errore, ma se il tuo programma ha uno scontro con un identificatore definito dall'implementazione, non è garantito che venga compilato o eseguito correttamente: è malformato. Sono inoltre vietati nomi che iniziano con un trattino basso seguito da una lettera maiuscola, tra gli altri. In generale, non iniziare le cose con caratteri di sottolineatura a meno che tu non sappia di quale magia stai trattando.

+0

Grazie per la punta !!! – nakiya

+3

Perché è vietato inoltrare dichiarazioni in 'namespace std' btw? – nakiya

+4

Dai un'occhiata a questa risposta (http://stackoverflow.com/questions/307343/forward-declare-an-stl-container/307408#307408) e alla discussione sui newsgroup collegati. –

9

La dichiarazione di inoltro deve avere l'elenco completo degli argomenti del modello specificato.

20

Ho risolto il problema.

Stavo implementando un livello OSI (finestra di scorrimento, livello 2) per una simulazione di rete in C++ (Eclipse Juno). Avevo i frame (modello <class T>) e i suoi stati (pattern di stato, dichiarazione di inoltro).

La soluzione è la seguente:

Nel file *.cpp, è necessario includere il file di intestazione che in avanti, vale a dire

ifndef STATE_H_ 
#define STATE_H_ 
#include <stdlib.h> 
#include "Frame.h" 

template <class T> 
class LinkFrame; 

using namespace std; 

template <class T> 
class State { 

    protected: 
    LinkFrame<int> *myFrame; 

} 

sua cpp:

#include "State.h" 
#include "Frame.h" 
#include "LinkFrame.h" 

template <class T> 
bool State<T>::replace(Frame<T> *f){ 

E ... un'altra classe.

+18

L'uso di qualsiasi 'utilizzo dello spazio dei nomi' in un file di intestazione è una pessima pratica perché impedisce a chiunque utilizzi quel file di intestazione di poter usare nomi locali che sarebbero altrimenti validi. In pratica, sconfigge l'intero punto dei namespace. –

-4

c'è un'alternativa limitato è possibile utilizzare

intestazione:

class std_int_vector; 

class A{ 
    std_int_vector* vector; 
public: 
    A(); 
    virtual ~A(); 
}; 

cpp:

#include "header.h" 
#include <vector> 
class std_int_vector: public std::vectror<int> {} 

A::A() : vector(new std_int_vector()) {} 
[...] 

non testato nei programmi reali, quindi aspettatevi di essere non perfetta.

Problemi correlati