Ошибка typedef: где поставить typedef и как его следует написать? - PullRequest
0 голосов
/ 13 октября 2011

Я пишу класс реализации btree 'btree' внутри файла btree.h и реализован внутри btree.tem с помощью внешнего класса итератора 'btree_iterator' в файле btree_iterator.h, реализованного в файле btree_iterator.tem

Вот (урезанное) содержимое btree.h:

#include "btree_iterator.h"

template <typename T> class btree 
{
 public:

  friend class btree_iterator<T>;
  typedef btree_iterator<T> iterator;

  iterator find(const T& elem);
};

#include "btree.tem"

Теперь при реализации функции поиска у меня есть следующая реализация заглушки в btree.tem:

template <typename T> iterator btree<T>::find(const T& elem) //LINE 24
{
    return NULL;
}

(я включил только строки кода, которые имеют отношение к моему вопросу)

При компиляции я получаю следующие ошибки:

btree.tem:24: error: expected constructor, destructor, or type conversion before 'btree'

Теперь я знаю, что это как-то связано с тем фактом, что я объявил typedef для итератора внутри объявления класса и поэтому ограничен областью действия только внутри этого блока. Но я попытался поместить другую строку typedef в btree.tem, но она просто не будет работать.

Как это должно быть написано?

Ответы [ 4 ]

3 голосов
/ 13 октября 2011

Напишите это:

template <typename T>
typename btree<T>::iterator btree<T>::find(const T& elem) //LINE 24
{
  //;;
}

Поскольку iterator является вложенным типом, вы должны написать btree<T>::iterator, а поскольку это зависимый вложенный тип, так как он зависит от типа аргумента шаблона T, вы также использовать typename:

  typename btree<T>::iterator
//^^^^^^^^ must use it as iterator is a dependent type!

См. Подробное объяснение здесь:

3 голосов
/ 13 октября 2011

Ваш возвращаемый тип не работает (в глобальной области видимости нет iterator), и вам нужно будет квалифицировать зависимый тип с помощью typename:

template <typename T>
typename btree<T>::iterator btree<T>::find(const T& elem)
{
    return NULL;
}
1 голос
/ 13 октября 2011

Области поиска в определении функции-члена немного асимметричны. Поиск возвращаемого типа выполняется во вложенной области видимости, а аргументы ищутся в области видимости класса. Это означает, что в то время как для аргументов вы можете использовать безусловное имя typedef, вы не можете сделать это для возвращаемого типа. Для иллюстративного примера:

struct test {
   typedef int integer;
   integer f( integer x );
};
// [1]                   [2]
test::integer test::f( integer x ) {
   return x;
}

Тип возвращаемого значения [1] находится в прилагаемой области имен, и в этой области integer не определено, поэтому его необходимо квалифицировать. С другой стороны, аргументы функции-члена ищутся внутри области видимости класса, поэтому вы можете использовать неквалифицированную integer там.

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

1 голос
/ 13 октября 2011

iterator - это вложенный тип в btree<T>.Когда вы определяете функцию, вы находитесь вне области действия класса, поэтому вам нужно квалифицировать тип как typename btree<T>::iterator.

...