2010-10-07 18 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 

y usé esa función en mi principal. Obtengo errores Por supuesto, sé que hay más parámetros de plantilla para std::list (asignador creo). Pero eso no viene al caso. ¿Tengo que saber la declaración de plantilla completa de una clase de plantilla para poder reenviarla?¿Cómo reenviar declarar una clase de plantilla en el espacio de nombres std?

EDITAR: No estaba usando un puntero antes, era una referencia. Lo probaré con el puntero.

+0

Y en el caso de la lista, el segundo parámetro es un parámetro predeterminado que es 'std :: allocator ' – nakiya

+2

. Se puede considerar como un descuido que el STL no contiene encabezados de declaración directa. Por otro lado, sus archivos se incluyen tan a menudo que probablemente no produzca ningún beneficio en el tiempo de compilación ... –

+6

'__TEST__' es un identificador reservado, [no lo use] (http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier). – GManNickG

Respuesta

116

El problema no es que no pueda reenviar-declarar una clase de plantilla. Sí, usted no necesita saber todos los parámetros de plantilla y sus valores predeterminados para poder visión de declarar correctamente:

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

Pero para hacer incluso una declaración de este tipo hacia adelante en namespace std está explícitamente prohibido por la norma : el único cosa que está permitido poner en std es una plantilla especialización, comúnmente std::less en un tipo definido por el usuario. Alguien más puede citar el texto relevante si es necesario.

Solo #include <list> y no te preocupes por eso.

Ah, dicho sea de paso, cualquier nombre que contenga doble subrayado está reservado para su uso por la implementación, por lo que debe utilizar algo como TEST_H en lugar de __TEST__. No va a generar una advertencia o un error, pero si su programa tiene un conflicto con un identificador definido por la implementación, no se garantiza que se compile o se ejecute correctamente: es mal formado. También están prohibidos los nombres que comienzan con un guión bajo seguido de una letra mayúscula, entre otros. En general, no empieces las cosas con guiones bajos a menos que sepas con qué magia estás tratando.

+0

Gracias por la sugerencia !!! – nakiya

+3

¿Por qué está prohibido reenviar declarar cosas en 'namespace std' btw? – nakiya

+4

Consulte esta respuesta (http://stackoverflow.com/questions/307343/forward-declare-an-stl-container/307408#307408) y la discusión del grupo de noticias vinculado. –

9

La declaración de reenvío debe tener lista de argumentos de plantilla completa especificada.

20

He resuelto ese problema.

Estaba implementando una capa OSI (ventana deslizante, Nivel 2) para una simulación de red en C++ (Eclipse Juno). Tenía marcos (plantilla <class T>) y sus estados (patrón de estado, declaración directa).

La solución es la siguiente:

En el archivo *.cpp, debe incluir el archivo de cabecera que hacia adelante, es decir

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; 

} 

Su CPP:

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

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

Y ... otra clase.

+18

Poner cualquier 'using namespace' en un archivo de encabezado es una práctica muy mala porque evita que cualquiera que use ese archivo de encabezado pueda usar nombres locales que de otro modo serían válidos. Básicamente, derrota el punto completo de los espacios de nombres. –

-4

hay una alternativa limitada puede utilizar

cabecera:

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()) {} 
[...] 

no probado en programas reales, por lo que esperan que sea no perfecta.

Cuestiones relacionadas