возвращать тип typedef при использовании отдельной компиляции - PullRequest
2 голосов
/ 04 декабря 2011

Вот файлы, над которыми я работаю:

class.h

#include <vector>

using std::vector;

template<class T>
class test {
private:
    vector<T> data;

public:

    typedef vector<T> vt;
    typedef typename vt::iterator it;

    test() {
    }
    ;
    it find(T x);
}

и class.cpp

#include "class.h"

it test::find(T x) {
    return find(data.begin(), data.end(), x);
}

Коды работают, если я помещу реализацию find внутри объявления класса.

Однако, когда я отделяю реализацию от класса, компилятор сообщает об ошибке «ожидаемый инициализатор перед тестированием».

Как это исправить? Проблема связана с областью применения typedef / typename?

Извините за мой плохой английский, это мой второй язык.

Пожалуйста, укажите любую ошибку в моих кодах, а также в моем английском

Спасибо за вашу помощь .:D

Ответы [ 2 ]

0 голосов
/ 05 декабря 2011

Когда компилятор видит it, он еще не может знать, что вы имеете в виду test<T>::it.Так что вы должны сказать это:

template<class T> typename test<T>::it test<T>::find(T x) {
    // The following line doesn't compile, but that's another issue:
    // return find(data.begin(), data.end(), x);
}

См. http://ideone.com/Rtho2 для рабочей программы.

0 голосов
/ 04 декабря 2011

Теперь шаблоны в C ++ нарушают этот принцип, bcoz C ++ - это скомпилированный язык. И компилятор генерирует весь необходимый код во время компиляции. Теперь, чтобы придерживаться ООП, мы получаем хрупкие шаблоны, которые на 100% не являются общими по своей природе.

Разделяйте декларацию и определения (реализация SHARING)

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

foo.h

Это простой файл, включающий foo_impl.h.

#ifndef FOO_H
#define FOO_H
template <class T>
class Foo {
  public:
    Foo (T);
    T get();
  private:
    T data;
};

#include "foo_impl.h"
#endif

foo_impl.h

Этот немного отличается от норм. Здесь мы не охраняем содержимое заголовочного файла. Вместо этого мы выдадим ошибку, если кто-то включит foo_impl.h напрямую (что в нашем случае не имеет смысла).

#ifndef FOO_H
#error 'foo_impl.h' is not supposed to be included directly. Include 'foo.h' instead.
#endif

template <class T>
Foo <T> :: Foo (T stuff) {
   data = stuff;
}

template <class T>
T Foo <T> :: get () {
   return data;
}

Теперь, если кто-то попытается включить foo_impl.h напрямую, получит ошибку вроде:

foo_impl.h:2:2: error: #error 'foo_impl.h' is not supposed to be included directly. Include 'foo.h' instead.

ПЛЮСЫ:

  • Разделение задач, реализация и декларации находятся в отдельных файлах.
  • Файл реализации безопасной защиты, исключающий случайное включение.
  • Файл заголовка, используемый для включения, не раздувается с кодом реализации.

МИНУСЫ:

  • Как уже упоминалось выше, необходимо поделиться реализацией.

Хранить декларацию и определения отдельно (НЕ РАЗДЕЛИТЬ реализацию)

Чтобы не делиться кодом для шаблонов, вы должны определить все возможные типы данных, с которыми ваш шаблон может использоваться в файле .cc / .cpp, например:

template class foo< int >;
template class foo< double >;

ПЛЮСЫ:

  • Разделение задач, реализация и декларации находятся в отдельных файлах.
  • Не нужно делиться своей реализацией

МИНУСЫ:

  • Не слишком общий. Нужно знать заранее, что требуется.
...