Come inoltrare una classe modello nello spazio dei nomi 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 ho usato quella funzione nel mio principale. Ottengo errori. Certo, so che ci sono più parametri per std::list(allocatore credo). Ma non è questo il punto. Devo conoscere la dichiarazione di modello completa di una classe di modello per poterlo inoltrare?

EDIT: non avevo usato un puntatore prima - era un riferimento. Lo proverò con il puntatore.


E nel caso dell'elenco, il secondo parametro è un parametro predefinito che èstd::allocator<T>
nakiya

2
si potrebbe considerare una svista che la STL non contiene intestazioni di dichiarazione a termine. D'altra parte, i suoi file sono così spesso inclusi che probabilmente non produrrebbe alcun beneficio nel tempo di compilazione ...
Matthieu M.

7
__TEST__è un identificatore riservato, non usarlo .
GManNickG

1
possibile duplicato del problema di dichiarazione
diretta

Risposte:


146

Il problema non è che non è possibile dichiarare in avanti una classe modello. Sì, è necessario conoscere tutti i parametri del modello e i loro valori predefiniti per poterlo dichiarare correttamente in avanti:

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

Ma fare anche una tale dichiarazione in avanti namespace stdè esplicitamente vietato dallo standard: l' unica cosa che ti è consentito inserire stdè una specializzazione di modello , comunemente std::lesssu 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 contenente caratteri di sottolineatura è riservato per l'implementazione, quindi dovresti usare qualcosa di simile TEST_Hinvece di __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: è mal formato . Sono anche vietati i nomi che iniziano con un carattere di sottolineatura seguito da una lettera maiuscola, tra gli altri. In generale, non iniziare le cose con caratteri di sottolineatura a meno che tu non sappia con quale magia hai a che fare.


4
Perché è vietato inoltrare dichiarazioni in namespace stdbtw?
nakiya,

4
Dai un'occhiata a questa risposta ( stackoverflow.com/questions/307343/… ) e alla discussione del newsgroup collegata.
Jon Purdy,

7
Jon / Nakiya, perché non usare #pragma oncepiuttosto che # ifdef's. Oggi è supportato dalla maggior parte dei compilatori.
Mark Ingram,

11
@Mark: Perché è #pragma, ecco perché. Sebbene sia un'opzione.
Jon Purdy,

2
Ci sono milioni di duplicati di quella domanda. Basta cercare: stackoverflow.com/search?q=pragma+once
Jon Purdy

20

Ho risolto quel 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 (modello di stato, dichiarazione in avanti).

La soluzione è la seguente:

Nel *.cppfile, è necessario includere il file di intestazione che si inoltra, ad es

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;

}

Il suo cpp:

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

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

E ... un'altra classe.


34
Inserire qualsiasi using namespacein un file di intestazione è una brutta pratica perché impedisce a chiunque utilizzi quel file di intestazione di essere in grado di utilizzare nomi locali che sarebbero altrimenti validi. Fondamentalmente sconfigge l'intero punto degli spazi dei nomi.
Andy Dent,

10

La dichiarazione a termine deve contenere l'elenco completo degli argomenti del modello.


-5

c'è un'alternativa limitata che puoi usare

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 in programmi reali, quindi aspettatevi che non sia perfetto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.