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.