Làm thế nào để chuyển tiếp khai báo một lớp mẫu trong không gian tên 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

và sử dụng chức năng đó trong chính của tôi. Tôi nhận được lỗi. Tất nhiên, tôi biết rằng có nhiều thông số mẫu hơn cho std::list(cấp phát tôi nghĩ). Nhưng bên cạnh đó là điểm. Tôi có phải biết khai báo mẫu đầy đủ của một lớp mẫu để có thể chuyển tiếp khai báo không?

EDIT: Tôi đã không sử dụng một con trỏ trước đây - nó là một tài liệu tham khảo. Tôi sẽ thử nó với con trỏ.


Và trong trường hợp danh sách, tham số thứ hai là tham số mặc địnhstd::allocator<T>
nakiya

2
người ta có thể coi đó là một sự giám sát rằng STL không chứa các tiêu đề khai báo chuyển tiếp. Mặt khác, các tệp của nó thường được bao gồm đến mức có thể sẽ không mang lại bất kỳ lợi ích nào trong thời gian biên dịch ...
Matthieu M.

7
__TEST__là một định danh dành riêng, không sử dụng nó .
GManNickG

Câu trả lời:


146

Vấn đề không phải là bạn không thể chuyển tiếp khai báo một lớp mẫu. Có, bạn cần phải biết tất cả các tham số mẫu và mặc định của chúng để có thể chuyển tiếp khai báo chính xác:

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

Nhưng để làm cho ngay cả một tuyên bố chuyển tiếp như vậy namespace stdbị cấm theo tiêu chuẩn rõ ràng: điều duy nhất bạn được phép đưa vào stdlà một chuyên môn mẫu , thường là std::lesstrên một loại do người dùng xác định. Một số người khác có thể trích dẫn các văn bản có liên quan nếu cần thiết.

Chỉ #include <list> và đừng lo lắng về nó.

Ồ, thật tình cờ, bất kỳ tên nào chứa hai dấu gạch dưới được dành riêng để sử dụng cho việc triển khai, vì vậy bạn nên sử dụng một cái gì đó như TEST_Hthay vì __TEST__. Nó sẽ không tạo ra cảnh báo hoặc lỗi, nhưng nếu chương trình của bạn có xung đột với mã định danh do triển khai thực hiện, thì nó không được đảm bảo để biên dịch hoặc chạy chính xác: nó không đúng định dạng . Cũng bị cấm là những cái tên bắt đầu bằng một dấu gạch dưới và theo sau là chữ in hoa, trong số những cái khác. Nói chung, đừng bắt đầu mọi thứ với dấu gạch dưới trừ khi bạn biết bạn đang đối phó với phép thuật nào.


4
Tại sao nó bị cấm để chuyển tiếp tuyên bố những điều trong namespace stdbtw?
nakiya

4
Kiểm tra câu trả lời này ( stackoverflow.com/questions/307343/ - ) và thảo luận nhóm tin được liên kết.
Jon Purdy

7
Jon / Nakiya, tại sao không sử dụng #pragma oncechứ không phải là # ifdef. Nó được hỗ trợ bởi hầu hết các trình biên dịch ngày nay.
Đánh dấu Ingram

11
@Mark: Bởi vì đó #pragmalà lý do tại sao. Mặc dù nó là một lựa chọn.
Jon Purdy

2
Có rất nhiều bản sao của câu hỏi đó. Chỉ cần tìm kiếm: stackoverflow.com/search?q=pragma+once
Jon Purdy

20

Tôi đã giải quyết vấn đề đó.

Tôi đã triển khai Lớp OSI (cửa sổ trượt, Cấp độ 2) cho mô phỏng mạng trong C ++ (Eclipse Juno). Tôi đã có khung (mẫu<class T> ) và trạng thái của nó (mẫu trạng thái, khai báo chuyển tiếp).

Giải pháp như sau:

Trong *.cpptệp, bạn phải bao gồm tệp Tiêu đề mà bạn chuyển tiếp, nghĩa là

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;

}

Cpp của nó:

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

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

Và ... một lớp học khác.


34
Đặt bất kỳ using namespacevào một tệp tiêu đề là một thực tế rất xấu bởi vì nó ngăn không cho bất kỳ ai sử dụng tệp tiêu đề đó có thể sử dụng tên địa phương có thể hợp lệ. Về cơ bản nó đánh bại toàn bộ điểm của không gian tên.
Andy Dent

10

Khai báo chuyển tiếp nên có danh sách đối số mẫu hoàn chỉnh được chỉ định.


-5

có một sự thay thế hạn chế bạn có thể sử dụng

tiêu đề:

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

không được thử nghiệm trong các chương trình thực tế, vì vậy mong đợi nó không hoàn hảo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.