ошибки переноса шаблонов C ++ из GCC в Visual C ++ - PullRequest
1 голос
/ 04 августа 2010

Следующие компиляции в GCC:

cvec.hpp:

template <class T>
class cvec : public deque<T>
{    
   class deque<T>::iterator Find(T);
};

cvec.cpp:

template <class T> 
class deque<T>::iterator cvec<T>::Find(T element)
{

}

В Visual C ++ получить:

ошибка C2242 "имя typedef не может следовать за class / struct / union.

Я изменил" class "в заголовочном файле на" typename ", но получил ошибку C3860 - список аргументов шаблона должен перечислять параметры в порядкеиспользуется в списке параметров шаблона. В этом случае есть только один параметр, T. Если компилятор не запутался в Find (элемент T)?

Ответы [ 3 ]

4 голосов
/ 05 августа 2010

Что это должно означать в заголовке:

class deque<T>::iterator Find(T);

Вы не объявляете класс.Ключевое слово typename здесь будет правильным, но class не имеет смысла.

То же самое верно и для файла .cpp:

template <class T> 
typename deque<T>::iterator cvec<T>::Find(T element)

правильно, classне так.

Помимо этого, действительно, похоже, что вы пытаетесь сделать, это ужасная идея.std::deque уже имеет функцию find.Оно работает.Это правильно.Это эффективно.Нет необходимости изобретать его заново.

Стандартные контейнеры библиотеки также не предназначены для наследования.У них нет виртуальных деструкторов.

Все, чего вы достигнете (кроме ошибок компиляции), это то, что вы в конечном итоге получите глючный, менее эффективный контейнерный класс, который запутает других программистов C ++потому что он не использует идиоматический интерфейс.

1 голос
/ 05 августа 2010

Это действительно должен быть комментарий, но я делаю его ответом, чтобы я мог отформатировать его для удобства чтения.

@ jalf и @dvl - Как было сказано выше @dvl, ни один из контейнеров std не имеет виртуальных деструкторов.Почему это имеет значение?

Допустим, вы получили класс "X" из std :: deque.

class X : public std::deque<int>
{
    // whatever ...
};

Давайте теперь скажем, что у вас есть объект "X", на который указывает базовый указатель.

std::deque<int> *p = new X;

и вы удалите его

delete p;

Деструктор для производного класса X не будет вызван, что может привести к множеству проблем.

Ваши параметры:
1. Не производные от контейнеров std.Сделайте их членами данных и напишите оболочки для предоставления функциональности.
2. Производные от контейнеров std только в том случае, если у производного класса нет деструктора и нет элементов данных с деструкторами.
3. Если вы производны от контейнера std,обратитесь к нему с помощью базового указателя.

После создания класса иногда трудно понять, как этот класс может использоваться в будущем.По этой причине многие разработчики строго придерживаются варианта «1».Лично я разрешаю извлекать из стандартного контейнера, если он хорошо документирован и используется с осторожностью.

0 голосов
/ 04 августа 2010

Это работает для меня в 2010 году:

#include <deque>

template <class T>
class cvec : public std::deque<T>
{    
public:
  typedef typename std::deque<T>::iterator iterator; 
  iterator Find(T element);
};

template <class T> 
typename cvec<T>::iterator cvec<T>::Find(T element)
{
  return std::deque<T>::iterator();
}

using namespace std;

int main()
{
  cvec<int> c;
  c.Find(1);

  return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...