Як переслати декларувати шаблон шаблону в просторі імен 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

і використовував цю функцію в моєму головному. Я отримую помилки. Звичайно, я знаю, що існує більше параметри шаблонів для std::list(розподільник, я думаю). Але це вже не в питанні. Чи повинен я знати повну декларацію шаблону класу шаблонів, щоб мати можливість переслати його?

EDIT: Раніше я не використовував покажчик - це було посиланням. Я спробую спробувати вказівник.


А у випадку списку другий параметр - це параметр за замовчуванням, який єstd::allocator<T>
nakiya

2
можна вважати недоглядом те, що STL не містить заголовків декларації вперед. З іншого боку, його файли настільки часто включаються, що, ймовірно, не принесуть ніякої користі під час компіляції ...
Матьє М. Окт

7
__TEST__є зарезервованим ідентифікатором, не використовуйте його .
GManNickG

1
можливий дублікат проблеми C ++ вперед - декларація
iammilind

Відповіді:


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/… ) та пов'язаною дискусією групи новин.
Джон Перді

7
Джон / Накія, чому б не використовувати, #pragma onceа не # ifdef. Цього дня його підтримує більшість компіляторів.
Позначте Інграма

11
@Mark: Тому що це #pragma, ось чому. Хоча це варіант.
Джон Перді

2
Існують прокрутки дублікатів цього питання. Просто шукайте: stackoverflow.com/search?q=pragma+once
Джон Перді,

20

Я вирішив цю проблему.

Я реалізував шар OSI (слайдерне вікно, рівень 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файлу в заголовок - дуже погана практика, оскільки він не дозволяє комусь із цього файлу заголовка користуватися локальними іменами, які б інакше були дійсними. Це в основному перемагає всю точку просторів імен.
Енді Дент,

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

не перевіряється в реальних програмах, тому очікуйте, що це буде не ідеально.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.