Como encaminhar declarar uma classe de modelo no namespace std?

131
#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 usei essa função no meu principal. Eu recebo erros. Claro, eu sei que existem mais parâmetros de modelo para std::list(alocador, eu acho). Mas isso não vem ao caso. Preciso conhecer a declaração de modelo completa de uma classe de modelo para poder encaminhá-la?

Edição: Eu não estava usando um ponteiro antes - era uma referência. Vou experimentar com o ponteiro.

nakiya
fonte
E no caso da lista, o segundo parâmetro é um parâmetro padrão que éstd::allocator<T>
nakiya
2
pode-se considerar que o STL não contém cabeçalhos de declaração direta. Por outro lado, seus arquivos são tantas vezes incluído que provavelmente não daria qualquer benefício no tempo de compilação ...
Matthieu M.
7
__TEST__é um identificador reservado, não o use .
GManNickG 7/10/10
1
possível duplicata de C ++ problema declaração para a frente
iammilind

Respostas:

146

O problema não é que você não pode declarar adiante uma classe de modelo. Sim, você precisa conhecer todos os parâmetros do modelo e seus padrões para poder declara-lo corretamente corretamente:

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

Mas fazer até mesmo uma declaração encaminhada namespace stdé explicitamente proibida pelo padrão: a única coisa que você pode inserir stdé uma especialização de modelo , geralmente std::lessem um tipo definido pelo usuário. Outra pessoa pode citar o texto relevante, se necessário.

Somente #include <list> e não se preocupe com isso.

Ah, aliás, qualquer nome que contenha sublinhado duplo é reservado para uso pela implementação; portanto, você deve usar algo como em TEST_Hvez de __TEST__. Não vai gerar um aviso ou erro, mas se o seu programa tiver um conflito com um identificador definido pela implementação, não será garantido que ele seja compilado ou executado corretamente: está mal formado . Também são proibidos nomes que começam com um sublinhado seguido por uma letra maiúscula, entre outros. Em geral, não comece as coisas com sublinhados, a menos que você saiba com que mágica está lidando.

Jon Purdy
fonte
4
Por que é proibido encaminhar declarar coisas em namespace stdbtw?
nakiya
4
Confira esta resposta ( stackoverflow.com/questions/307343/… ) e a discussão do grupo de notícias vinculado.
Jon Purdy
7
Jon / Nakiya, por que não usar #pragma onceem vez dos # ifdef's. É suportado pela maioria dos compiladores atualmente.
Mark Ingram
11
@ Mark: Porque é #pragma, é por isso. Embora seja uma opção.
quer
2
Existem milhões de duplicatas dessa pergunta. Basta pesquisar: stackoverflow.com/search?q=pragma+once
Jon Purdy
20

Eu resolvi esse problema.

Eu estava implementando uma camada OSI (janela deslizante, nível 2) para uma simulação de rede em C ++ (Eclipse Juno). Eu tinha quadros (modelo<class T> ) e seus estados (padrão de estado, declaração direta).

A solução é a seguinte:

No *.cpparquivo, você deve incluir o arquivo de cabeçalho que encaminhar, ou seja

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;

}

Seu cpp:

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

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

E ... outra aula.

user1638075
fonte
34
Colocar qualquer item using namespaceem um arquivo de cabeçalho é uma prática muito ruim, pois impede que qualquer pessoa que use esse arquivo de cabeçalho possa usar nomes locais que, de outra forma, seriam válidos. Basicamente, derrota todo o ponto dos espaços para nome.
Andy Dent
10

A declaração de encaminhamento deve ter a lista completa de argumentos do modelo especificada.

Grozz
fonte
-5

existe uma alternativa limitada que você pode usar

cabeçalho:

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

não testado em programas reais, portanto, espere que não seja perfeito.

Arne
fonte