Declaración directa de un typedef en C ++

¿Por qué el comstackdor no me deja avanzar para declarar un typedef?

Asumiendo que es imposible, ¿cuál es la mejor práctica para mantener mi árbol de inclusión pequeño?

Puede hacer reenviar typedef. Pero para hacer

typedef AB; 

primero debe reenviar declarar A :

 class A; typedef AB; 

Para aquellos de ustedes que me quieren, que están buscando reenviar, declaran una estructura C-style que se definió usando typedef, en algún código c ++, he encontrado una solución que dice lo siguiente …

 // 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; } 

En C ++ (pero no en C simple), es perfectamente legal escribir typedef un tipo dos veces, siempre que ambas definiciones sean completamente idénticas:

 // 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); 

Para “fwd declare un typedef” necesitas forw declarar una clase o una estructura y luego puedes escribir el tipo declarado dedef. Múltiples typedefs idénticos son aceptables por el comstackdor.

forma larga:

 class MyClass; typedef MyClass myclass_t; 

forma corta:

 typedef class MyClass myclass_t; 

Porque para declarar un tipo, su tamaño necesita ser conocido. Puede reenviar declarar un puntero al tipo, o typedef un puntero al tipo.

Si realmente lo deseas, puedes usar el modismo pimpl para mantener los números abajo. Pero si desea utilizar un tipo, en lugar de un puntero, el comstackdor debe conocer su tamaño.

Editar: j_random_hacker agrega una calificación importante a esta respuesta, básicamente que se necesita saber el tamaño para usar el tipo, pero se puede hacer una statement directa si solo necesitamos saber que el tipo existe , para crear punteros o referencias al tipo. Como el OP no mostraba el código, pero se quejaba de que no comstackría, asumí (probablemente correctamente) que el OP intentaba usar el tipo, no solo referirse a él.

El uso de declaraciones directas en lugar de un #include total completo es posible solo cuando no se pretende usar el tipo en sí (en el scope de este archivo) sino un puntero o referencia a él.

Para usar el tipo en sí, el comstackdor debe conocer su tamaño, por lo tanto, se debe ver su statement completa, por lo tanto, se necesita un #include completo.

Sin embargo, el comstackdor conoce el tamaño de un puntero o referencia, independientemente del tamaño de la punta, por lo que una statement directa es suficiente: declara un nombre de identificador de tipo.

Curiosamente, cuando se utiliza puntero o referencia a class o tipo de struct , el comstackdor puede manejar tipos incompletos, lo que le ahorra la necesidad de reenviar declarar también los tipos de punta:

 // 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 

Tuve el mismo problema, no quería meterme con múltiples typedefs en diferentes archivos, así que lo resolví con herencia:

estaba:

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

hizo:

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

Trabajado como un encanto. Por supuesto, tuve que cambiar cualquier referencia de

 BurstBoss::ParticleSystem 

simplemente

 ParticleSystem 

Como notó Bill Kotsias, la única manera razonable de mantener los detalles typedef de su punto es privado, y reenviarlos declararlos es con herencia. Sin embargo, puedes hacerlo un poco mejor con C ++ 11. Considera esto:

 // 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; }; 

Al igual que @BillKotsias, utilicé la herencia, y funcionó para mí.

Cambié este desastre (que requería todos los encabezados de impulso en mi statement * .h)

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

en esta statement (* .h)

 class VanillaAccumulator; std::unique_ptr acc; 

y la implementación (* .cpp) era

 #include  #include  #include  #include  #include  #include  #include  class VanillaAccumulator : public boost::accumulators::accumulator_set> { };