Форвардное объявление typedef в C ++

Почему компилятор не позволяет мне объявить typedef?

Предполагая, что это невозможно, какова наилучшая практика сохранения моего дерева включения?

9 Solutions collect form web for “Форвардное объявление typedef в C ++”

Вы можете выполнить форматирование typedef. Но делать

typedef AB; 

вы должны сначала направить объявление A :

 class A; typedef AB; 

Для тех из вас, как я, которые ищут вперед, объявляют структуру C-стиля, которая была определена с помощью typedef, в каком-то c ++-коде я нашел решение, которое выглядит следующим образом …

 // ah typedef struct _bah { int a; int b; } bah; // bh struct _bah; typedef _bah bah; class foo { foo(bah * b); foo(bah b); bah * mBah; }; // b.cpp #include "bh" #include "ah" foo::foo(bah * b) { mBah = b; } foo::foo(bah b) { mBah = &b; } 

В C ++ (но не просто C) вполне законно печатать тип дважды, если оба определения полностью идентичны:

 // foo.h struct A{}; typedef A *PA; // bar.h struct A; // forward declare A typedef A *PA; void func(PA x); // baz.cc #include "bar.h" #include "foo.h" // We've now included the definition for PA twice, but it's ok since they're the same ... A x; func(&x); 

Чтобы «fwd объявить typedef», вам нужно объявить class или структуру, а затем вы можете объявить тип typedef. Компилятор допускает несколько идентичных typedef.

длинная форма:

 class MyClass; typedef MyClass myclass_t; 

короткая форма:

 typedef class MyClass myclass_t; 

Поскольку для объявления типа необходимо знать его размер. Вы можете переслать объявление указателя на тип или typedef указатель на тип.

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

Редактировать: j_random_hacker добавляет важную квалификацию к этому ответу, в основном, что размер должен быть известен, чтобы использовать тип, но может быть сделано объявление вперед, если нам нужно только знать тип существует , чтобы создать указатели или ссылки на тип. Поскольку ОП не показывал код, но жаловался, что он не будет компилироваться, я предположил (возможно, правильно), что ОП пытался использовать этот тип, а не просто ссылался на него.

Использование форвардных деклараций вместо полного #include s возможно только тогда, когда вы не собираетесь использовать сам тип (в области этого файла), но указатель или ссылку на него.

Чтобы использовать сам тип, компилятор должен знать его размер – следовательно, его полная декларация должна быть видна – следовательно, необходим полный #include .

Однако размер указателя или ссылки известен компилятору, независимо от размера указателя, поэтому достаточно объявления прямого объявления – оно объявляет имя идентификатора типа.

Интересно отметить, что при использовании указателя или ссылки на типы class или struct компилятор может обрабатывать неполные типы, сохраняя при этом необходимость пересылать объявления также и типов указателей:

 // header.h // Look Ma! No forward declarations! typedef class A* APtr; // class A is an incomplete type - no fwd. decl. anywhere typedef class A& ARef; typedef struct B* BPtr; // struct B is an incomplete type - no fwd. decl. anywhere typedef struct B& BRef; // Using the name without the class/struct specifier requires fwd. decl. the type itself. class C; // fwd. decl. type typedef C* CPtr; // no class/struct specifier typedef C& CRef; // no class/struct specifier struct D; // fwd. decl. type typedef D* DPtr; // no class/struct specifier typedef D& DRef; // no class/struct specifier 

У меня была такая же проблема, я не хотел связываться с несколькими typedefs в разных файлах, поэтому решил ее с наследованием:

был:

 class BurstBoss { public: typedef std::pair ParticleSystem; // removed this with... 

сделал:

 class ParticleSystem : public std::pair { public: ParticleSystem(Ogre::ParticleSystem* system, bool enabled) : std::pair(system, enabled) { }; }; 

Работал как шарм. Конечно, мне пришлось изменить любые ссылки из

 BurstBoss::ParticleSystem 

просто

 ParticleSystem 

Как отметил Билл Коциас, единственный разумный способ сохранить данные typedef вашего персонажа в частном порядке, а вперед – объявить их с наследованием. Вы можете сделать это немного лучше с C ++ 11. Учти это:

 // LibraryPublicHeader.h class Implementation; class Library { ... private: Implementation* impl; }; 
 // LibraryPrivateImplementation.cpp // This annoyingly does not work: // // typedef std::shared_ptr Implementation; // However this does, and is almost as good. class Implementation : public std::shared_ptr { public: // C++11 allows us to easily copy all the constructors. using shared_ptr::shared_ptr; }; 

Как @BillKotsias, я использовал наследование, и это сработало для меня.

Я изменил этот беспорядок (который требовал всех заголовков boost в моей декларации * .h)

 #include  #include  #include  #include  #include  #include  #include  typedef boost::accumulators::accumulator_set> VanillaAccumulator_t ; std::unique_ptr acc; 

в эту декларацию (* .h)

 class VanillaAccumulator; std::unique_ptr acc; 

и реализация (* .cpp) была

 #include  #include  #include  #include  #include  #include  #include  class VanillaAccumulator : public boost::accumulators::accumulator_set> { }; 
  • Понимание typedefs для указателей функций в C
  • Обеспечьте сильную проверку типов в C (строгость строгости для typedefs)
  • Разница между 'struct' и 'typedef struct' в C ++?
  • Статический polymorphism C ++ (CRTP) и использование typedefs из производных classов
  • Что такое «форвардная декларация» и разница между «typedef struct X» и «struct X»?
  • Непрозрачные C-структуры: как их объявить?
  • Почему мы должны набирать структуру так часто в C?
  • Указатель функции Typedef?
  • Как typedef работает для указателей функций
  • Это хорошая идея для указателей typedef?
  • Эквивалент typedef в C #
  • Давайте будем гением компьютера.