C++ template compilation error-рекурсивная зависимость типа или функции

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

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 ответов


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

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

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

теперь вижу ошибку:

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

ошибка говорит все. .7.1 из стандарта очень хорошо объясняет причину вашей проблемы, давая вам даже пример, который очень близок к тому, что вы делаете. Так что мне даже не нужно писать одно мое слово. Вот .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;

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


EDIT: но мне интересно, чего вы пытаетесь достичь с Entity<T*> pPrev? Кажется, это опечатка, и вы, вероятно, хотели написать Entity<T>* pPrev. То же самое с pNext. Так ли это?

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

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

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


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

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

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

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


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

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


изменить

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

to

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

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


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