จะส่งต่อประกาศคลาสเทมเพลตในเนมสเปซ 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

และใช้ฟังก์ชันนั้นใน main ฉันได้รับข้อผิดพลาด แน่นอนฉันรู้ว่ามีพารามิเตอร์เทมเพลตเพิ่มเติมสำหรับstd::list(ฉันคิดว่าตัวจัดสรร) แต่ที่อยู่ข้างประเด็น ฉันต้องรู้การประกาศเทมเพลตแบบเต็มของคลาสเทมเพลตเพื่อส่งต่อประกาศได้หรือไม่

แก้ไข: ฉันไม่ได้ใช้ตัวชี้มาก่อน - มันเป็นข้อมูลอ้างอิง ฉันจะลองใช้ตัวชี้


และในกรณีของรายการพารามิเตอร์ที่สองเป็นพารามิเตอร์เริ่มต้นคือstd::allocator<T>
nakiya

2
อาจพิจารณาว่าเป็นการกำกับดูแลที่ STL ไม่มีส่วนหัวของการประกาศล่วงหน้า ในทางกลับกันไฟล์ของมันมักจะถูกรวมเอาไว้มากจนอาจจะไม่เกิดประโยชน์ใด ๆ ในเวลาการรวบรวม ...
Matthieu M.

7
__TEST__เป็นตัวระบุสงวนไม่ได้ใช้มัน
GManNickG

คำตอบ:


146

ปัญหาไม่ใช่ว่าคุณไม่สามารถประกาศคลาสแม่แบบส่งต่อได้ ใช่คุณจำเป็นต้องทราบพารามิเตอร์เทมเพลตทั้งหมดและค่าเริ่มต้นเพื่อให้สามารถประกาศไปข้างหน้าได้อย่างถูกต้อง:

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

แต่การที่จะทำให้การประกาศไปข้างหน้าnamespace stdนั้นถูกห้ามอย่างชัดเจนโดยมาตรฐาน: สิ่งเดียวที่คุณอนุญาตให้ใส่ได้stdคือความเชี่ยวชาญพิเศษของเทมเพลตโดยทั่วไปจะstd::lessอยู่ในประเภทที่ผู้ใช้กำหนดเอง บุคคลอื่นสามารถอ้างถึงข้อความที่เกี่ยวข้องได้หากจำเป็น

เพียง#include <list>และไม่ต้องกังวลกับมัน

โอ้บังเอิญชื่อใด ๆ ที่มีขีดสองครั้งที่สงวนไว้สำหรับการใช้งานโดยการดำเนินการดังนั้นคุณควรใช้สิ่งที่ต้องการแทนTEST_H __TEST__มันไม่ได้เป็นไปเพื่อสร้างคำเตือนหรือข้อผิดพลาด แต่ถ้าโปรแกรมของคุณมีการปะทะกันกับตัวระบุการดำเนินงานที่กำหนดไว้แล้วก็ไม่รับประกันว่าจะรวบรวมหรือทำงานอย่างถูกต้อง: มันไม่ดีเกิดขึ้น นอกจากนี้ยังห้ามชื่อที่ขึ้นต้นด้วยขีดล่างตามด้วยอักษรตัวใหญ่และอื่น ๆ โดยทั่วไปอย่าเริ่มต้นด้วยเครื่องหมายขีดล่างเว้นแต่คุณจะรู้ว่าคุณกำลังใช้เวทมนตร์อะไรอยู่


4
ทำไมจึงห้ามส่งต่อสิ่งที่ประกาศในnamespace stdbtw?
nakiya

4
ลองดูคำตอบนี้ ( stackoverflow.com/questions/307343/… ) และการสนทนากลุ่มข่าวที่เชื่อมโยง
Jon Purdy

7
จอน / นาคิยะทำไมไม่ใช้#pragma onceแทน # ifdef ได้รับการสนับสนุนโดยคอมไพเลอร์ส่วนใหญ่ในปัจจุบัน
Mark Ingram

11
@ มาร์ค: เพราะ#pragmaนั่นคือเหตุผล แม้ว่าจะเป็นตัวเลือก
Jon Purdy

2
มีคำถามซ้ำซ้อนของคำถามนั้น เพียงค้นหา: stackoverflow.com/search?q=pragma+once
Jon Purdy

20

ฉันแก้ปัญหานั้นแล้ว

ฉันกำลังใช้ OSI Layer (หน้าต่างตัวเลื่อนระดับ 2) สำหรับการจำลองเครือข่ายใน C ++ (Eclipse Juno) ฉันมีเฟรม (เทมเพลต<class T>) และสถานะ (รูปแบบสถานะการประกาศไปข้างหน้า)

วิธีแก้ปัญหามีดังนี้:

ใน*.cppไฟล์คุณต้องรวมไฟล์ส่วนหัวที่คุณส่งต่อเช่น

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 ของมัน:

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

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

และ ... อีกชั้น.


34
การใส่using namespaceไฟล์ส่วนหัวเป็นแนวทางปฏิบัติที่ไม่ดีอย่างยิ่งเนื่องจากจะป้องกันไม่ให้ใครก็ตามที่ใช้ไฟล์ส่วนหัวนั้นไม่สามารถใช้ชื่อโลคัลที่จะใช้ได้ โดยทั่วไปแล้วมันจะเอาชนะจุดทั้งหมดของเนมสเปซ
Andy Dent

10

การประกาศไปข้างหน้าควรมีการระบุรายการอาร์กิวเมนต์เทมเพลตที่สมบูรณ์


-5

มีทางเลือกที่ จำกัด ที่คุณสามารถใช้ได้

หัวข้อ:

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

ไม่ได้ทดสอบในโปรแกรมจริงดังนั้นคาดว่าจะไม่สมบูรณ์แบบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.