Шаблоны, вложенные классы и «ожидаемый конструктор, деструктор или преобразование перед символом« & » - PullRequest
3 голосов
/ 12 ноября 2009

Работая с некоторыми шаблонами и написав себе базовый контейнерный класс с итераторами, я обнаружил, что мне нужно переместить тело функций-членов из класса шаблона в отдельный файл, чтобы соответствовать рекомендациям по стилю. Однако я столкнулся с интересной ошибкой компиляции:

runtimearray.cpp: 17: ошибка: ожидается конструктор, деструктор или тип преобразование перед символом '&' runtimearray.cpp: 24: ошибка: ожидается конструктор, деструктор или тип преобразование перед символом '&' runtimearray.cpp: 32: ошибка: ожидается конструктор, деструктор или тип преобразование перед символом '&' runtimearray.cpp: 39: ошибка: ожидается конструктор, деструктор или тип преобразование перед символом '&' runtimearray.cpp: 85: ошибка: ожидается конструктор, деструктор или тип преобразование перед RuntimeArray runtimearray.cpp: 91: ошибка: ожидается конструктор, деструктор или тип преобразование до 'RuntimeArray'

runtimearray.h:

#ifndef RUNTIMEARRAY_H_
#define RUNTIMEARRAY_H_

template<typename T>
class RuntimeArray
{
 public:
  class Iterator
  {
    friend class RuntimeArray;
   public:
    Iterator(const Iterator& other);

    T& operator*();
    Iterator& operator++();
    Iterator& operator++(int);
    Iterator& operator--();
    Iterator& operator--(int);
    bool operator==(Iterator other);
    bool operator!=(Iterator other);

   private:
    Iterator(T* location);

    T* value_;
  };

  RuntimeArray(int size);
  ~RuntimeArray();

  T& operator[](int index);

  Iterator Begin();
  Iterator End();

 private:
  int size_;
  T* contents_;
};

#endif  // RUNTIMEARRAY_H_

runtimearray.cpp:

#include "runtimearray.h"

template<typename T>
RuntimeArray<T>::Iterator::Iterator(const Iterator& other)
    : value_(other.value_)
{
}

template<typename T>
T& RuntimeArray<T>::Iterator::operator*()
{
  return *value_;
}

template<typename T>
RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator++()
{
  ++value_;
  return *this;
}

template<typename T>
RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator++(int)
{
  Iterator old = *this;
  ++value_;
  return old;
}

template<typename T>
RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator--()
{
  --value_;
  return *this;
}

template<typename T>
RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator--(int)
{
  Iterator old = *this;
  --value_;
  return old;
}

template<typename T>
bool RuntimeArray<T>::Iterator::operator==(Iterator other)
{
  return value_ == other.value_;
}

template<typename T>
bool RuntimeArray<T>::Iterator::operator!=(Iterator other)
{
  return value_ != other.value_;
}

template<typename T>
RuntimeArray<T>::Iterator::Iterator(T* location)
    : value_(location)
{
}

template<typename T>
RuntimeArray<T>::RuntimeArray(int size)
    : size_(size),
      contents_(new T[size])
{
}

template<typename T>
RuntimeArray<T>::~RuntimeArray()
{
  if(contents_)
    delete[] contents_;
}

template<typename T>
T& RuntimeArray<T>::operator[](int index)
{
  return contents_[index];
}

template<typename T>
RuntimeArray<T>::Iterator RuntimeArray<T>::Begin()
{
  return Iterator(contents_);
}

template<typename T>
RuntimeArray<T>::Iterator RuntimeArray<T>::End()
{
  return Iterator(contents_ + size_);
}

Как я могу устранить эти ошибки? Файлы имеют смысл для меня, но, увы, важно то, что говорит компилятор.

Ответы [ 3 ]

12 голосов
/ 12 ноября 2009

Я думаю, что вам не хватает ключевого слова typename.

, например

template<typename T>
RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator++()

должно быть

template<typename T>
typename RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator++()

«Вложенным» типам, которые зависят от параметра шаблона, требуется ключевое слово typename, чтобы сообщить компилятору, что это должны быть типы, в противном случае это будет неоднозначно.

2 голосов
/ 12 ноября 2009

Это не будет работать так, как вы хотите. Все ваши объявления функций и определения должны появиться в файле .h, в котором вы определили RuntimeArray. Ошибка, которую вы видите, может быть чем-то иным, например, с именем типа, но даже если вы можете заставить RunTimeArray.cpp компилироваться изолированно, никто не сможет его использовать.

Если вы действительно должны иметь определения в отдельном файле, #include это в конце runtimearray.h

2 голосов
/ 12 ноября 2009

Это чертовски забавное руководство по стилю. Как правило, определения шаблонных функций должны содержать в заголовочном файле. Это произошло всего несколько часов назад: Разделение шаблонных классов C ++ на файлы .hpp / .cpp - возможно ли это?

...