Ошибка компиляции шаблона C ++ - рекурсивная зависимость типа или функции - PullRequest
7 голосов
/ 05 декабря 2010

Я написал шаблонный класс, который дает ошибку компиляции

template<class T>
class Entity
{
    string EntityName;
    int  EntitySize;
    Entity<T*> pPrev;
    Entity<T*> pNext;
public:
    Entity<T>(const string & name, int size)
    {
        EntityName = name;
        EntitySize = size;
    }
    //member functions
};

Я использую MSVC ++ 2008, и ошибка:

фатальная ошибка C1202: рекурсивный тип или функцияслишком сложный контекст зависимости

Я не написал ни одной рекурсивной функции в своем классе.Тогда почему эта ошибка?Пожалуйста, помогите.

Ответы [ 5 ]

11 голосов
/ 05 декабря 2010

Хорошо.Я объясняю вам проблему, с которой вы сталкиваетесь.Но первым делом первым.Вы сказали:

Я написал шаблонный класс, который выдает ошибку компиляции

Прежде всего, что касается C ++, такого не существуетв качестве «шаблона класса» существует только «шаблон класса». Способ чтения этой фразы - «шаблон для класса», а не «шаблон функции», который является «шаблоном дляфункция «.Опять же: классы не определяют шаблоны, шаблоны определяют классы (и функции). * Цитируется здесь .

Теперь давайте посмотрим на ошибку:

fatalошибка C1202: слишком сложный контекст зависимости рекурсивного типа или функции

Ошибка говорит сама за себя.$14.7.1 из Стандарта очень хорошо объясняет причину вашей проблемы, давая вам даже пример, очень близкий к тому, что вы делаете.Так что мне даже не нужно писать ни одного моего слова.Вот $14.7.1

4 Существует определенное реализацией количество, которое определяет ограничение на общую глубину рекурсивных реализаций , которое может включать более одного шаблона. Результат бесконечной рекурсии в экземпляре не определен. [Пример:

template < class T > class X {
X<T >* p; // OK
X<T*> a; //implicit generation of X<T> requires
         //the implicit instantiation of X<T*> which requires
         //the implicit instantiation of X<T**> which ...
};

- конец примера]

Прочитайте комментарий с X<T*> aчто в значительной степени относится и к вам.Таким образом, ваша проблема не из-за рекурсивной функции, а из-за рекурсивного создания шаблона класса , вызывающего из следующих строк:

  Entity<T*> pPrev;
  Entity<T*> pNext;

Надеюсь, это решит вашу проблему!


РЕДАКТИРОВАТЬ: Но мне интересно, что вы пытаетесь достичь с Entity<T*> pPrev?Кажется, это опечатка, и вы, вероятно, хотели написать Entity<T>* pPrev.То же самое с pNext.Это так?

И совет по улучшению дизайна: используйте список инициализации элемента вместо назначения.То есть напишите свой конструктор следующим образом:

    Entity<T>(const string & name, int size) : EntityName(name), EntitySize(size)
    {
       //all assignments moved to initialization list.
    }

Прочитайте это: Почему я предпочитаю использовать список инициализации членов?

7 голосов
/ 05 декабря 2010

Внимательно прочитайте сообщение об ошибке. «Слишком сложная» вещь - это не рекурсивная функция, это рекурсивная тип или зависимость от функции . Тип Entity<T*> зависит от типа Entity<T> рекурсивно. Когда компилятор пытается сгенерировать код для Entity<int>, он должен вычислить Entity<int*> (для реализации элементов pPrev и pNext), что означает, что он должен выяснить Entity<int**>, и т.д. - бесконечно. Это не разрешено.

Но компилятор знает, что что-то не так. Он не знает, что не так, потому что не может думать о том, как программировать. (Если бы он мог, он просто написал бы вашу программу для вас.)

Логическая ошибка в том, что Entity<T*> означает «объект, который является сущностью с указателем на T типа шаблона». Что вы действительно хотели, чтобы создать связанный список, так это «указатель на объект, который является сущностью с типом шаблона T». Это пишется Entity<T>*, с * вне угловых скобок.

Но настоящая проблема заключается в том, что вы пытаетесь создать свой собственный связанный список. Не делай этого . Используйте стандартные библиотеки контейнеров. Если вы достаточно умны, чтобы использовать std::string, вы должны быть достаточно умны, чтобы использовать контейнеры (std::vector, std::list и т. Д. - в некотором смысле, std::string - это тоже контейнер, хотя и очень особенный - тоже один)

3 голосов
/ 05 декабря 2010

Ваше определение шаблона бесконечно рекурсивно.Вы определяете шаблонный класс Entity<T>, который содержит объекты типа Entity<T*> в качестве членов.Объекты Entity<T*> будут, согласно тому же определению, содержать объекты типа Entity<T**>.Последний, в свою очередь, будет содержать объекты типа Entity<T***> и так далее, как бесконечность.Другими словами, ваше бесконечно рекурсивное определение шаблона не имеет смысла.

Либо прекратите рекурсию, либо подумайте, что вы действительно пытаетесь реализовать.Я сильно подозреваю, что ваши определения членов должны были иметь тип Entity<T>*, а не Entity<T*>.

2 голосов
/ 05 декабря 2010

Изменить

    Entity<T*> pPrev;
    Entity<T*> pNext;

на

    Entity<T> *pPrev;
    Entity<T> *pNext;

Ваше определение типа является рекурсивным ...

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

Вы написали рекурсивный тип. Сущность имеет других членов Сущности. Вы должны изменить членов Entity на указатель или ссылку.

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