Bagaimana cara meneruskan mendeklarasikan kelas templat di 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

dan menggunakan fungsi itu di main saya. Saya mendapatkan kesalahan. Tentu saja, saya tahu bahwa ada lebih banyak params template untuk std::list(pengalokasi saya pikir). Tapi, itu intinya. Apakah saya harus mengetahui deklarasi templat lengkap dari kelas templat untuk dapat meneruskannya mendeklarasikannya?

EDIT: Saya tidak menggunakan pointer sebelumnya - itu adalah referensi. Saya akan mencobanya dengan pointer.

nakiya
sumber
Dan dalam hal daftar, parameter kedua adalah parameter default yaitustd::allocator<T>
nakiya
2
orang dapat menganggapnya sebagai kekeliruan bahwa STL tidak mengandung tajuk deklarasi maju. Di sisi lain, file-file ini sangat sering disertakan sehingga mungkin tidak akan menghasilkan manfaat apa pun pada waktu kompilasi ...
Matthieu M.
7
__TEST__adalah pengidentifikasi yang dilindungi undang-undang, jangan gunakan itu .
GManNickG
1
kemungkinan duplikat masalah deklarasi maju C ++
iammilind

Jawaban:

146

Masalahnya bukan bahwa Anda tidak dapat meneruskan-mendeklarasikan kelas templat. Ya, Anda perlu mengetahui semua parameter template dan default-nya untuk dapat meneruskannya dengan benar:

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

Tetapi untuk membuat bahkan deklarasi maju semacam namespace stditu secara eksplisit dilarang oleh standar: satu - satunya hal yang Anda boleh masukkan stdadalah spesialisasi templat , biasanya std::lesspada tipe yang ditentukan pengguna. Orang lain dapat mengutip teks yang relevan jika perlu.

Hanya #include <list>dan jangan khawatir tentang itu.

Oh, kebetulan, nama apa pun yang berisi garisbawah ganda dicadangkan untuk digunakan oleh implementasi, jadi Anda harus menggunakan sesuatu seperti TEST_Hsebagai ganti __TEST__. Itu tidak akan menghasilkan peringatan atau kesalahan, tetapi jika program Anda memiliki bentrokan dengan pengidentifikasi yang ditentukan implementasi, maka itu tidak dijamin untuk dikompilasi atau dijalankan dengan benar: itu salah bentuk . Juga dilarang adalah nama yang dimulai dengan garis bawah diikuti dengan huruf kapital, antara lain. Secara umum, jangan memulai sesuatu dengan menggarisbawahi kecuali Anda tahu sihir apa yang Anda hadapi.

Jon Purdy
sumber
4
Mengapa dilarang untuk menyatakan sesuatu di namespace stdbtw?
nakiya
4
Lihatlah jawaban ini ( stackoverflow.com/questions/307343/… ) dan diskusi newsgroup yang tertaut.
Jon Purdy
7
Jon / Nakiya, mengapa tidak menggunakan #pragma oncedaripada # ifdef. Ini didukung oleh sebagian besar kompiler hari ini.
Tandai Ingram
11
@ Mark: Karena itu #pragma, itu sebabnya. Padahal itu pilihan.
Jon Purdy
2
Ada gesekan duplikat dari pertanyaan itu. Cukup cari: stackoverflow.com/search?q=pragma+once
Jon Purdy
20

Saya memecahkan masalah itu.

Saya menerapkan Lapisan OSI (jendela geser, Level 2) untuk simulasi jaringan di C ++ (Eclipse Juno). Saya punya bingkai (templat <class T>) dan statusnya (pola negara, pernyataan maju).

Solusinya adalah sebagai berikut:

Dalam *.cppfile tersebut, Anda harus menyertakan file Header yang Anda teruskan, yaitu

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;

}

Itu cpp:

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

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

Dan ... kelas lain.

pengguna1638075
sumber
34
Menempatkan apa pun using namespacedi file header adalah praktik yang sangat buruk karena mencegah siapa pun yang menggunakan file header itu tidak dapat menggunakan nama lokal yang seharusnya valid. Ini pada dasarnya mengalahkan seluruh titik ruang nama.
Andy Dent
10

Deklarasi maju harus memiliki daftar argumen templat lengkap yang ditentukan.

Grozz
sumber
-5

ada alternatif terbatas yang bisa Anda gunakan

tajuk:

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

tidak diuji dalam program nyata, jadi harap itu tidak sempurna.

Arne
sumber