0

I'm using a physics library called Bullet and I'm having trouble preventing including the Bullet headers into my Physics header.

//Physics.h
#include <BulletPhysics/btBulletDynamicsCommon.h> // Contains lots of other headers

struct Physics
{
    static btDiscreteDynamicsWorld* pDynamicsWorld;
    static btAlignedObjectArray<btCollisionShape*> collisionShapes;
    static vec3 findSomePoint();
};

Now in various other parts of my code I may want to access the Physics struct, and to do this I need to include the Physics header, but that will also include all the library headers in any other CPP file.

I'm trying to figure a way to have the library headers only included in Physics.cpp, but I'm having trouble getting the compiler to recognise the library types in the struct definition if I remove the header from Physics.h.

With some of the members I can just forward declare and that works fine, but it's not going to work for non pointer or reference types as the full definition is needed.

I noticed that if I use a namespace I can get away with declaring a member as extern, and the full type definition isn't needed. But it results in weird things with the forward declarations:

struct btDiscreteDynamicsWorld; // This seems fine
template <typename T>
struct btAlignedObjectArray; // This works but seems really hacky and I'm not sure if it's even valid

namespace Physics
{
    extern btDiscreteDynamicsWorld* pDynamicsWorld;
    extern btAlignedObjectArray<btCollisionShape*> collisionShapes; // Complete type not needed
    vec3 findSomePoint();
}

Also using a namespace I lose the ability to use access specifiers.

I also thought instead of having the members themselves in the struct I could use getter functions and return references, but the return types also need at least a forward declaration (not complete type I think), and I would still have to forward declare that template type the way I did earlier.

Which is the best way to do this? Or am I placing too much emphasis on preventing the copying of extra headers. That one header contains many many other headers, so it is quite a lot, so I'm not sure if I should care or not.

Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • Don't bother with stuff like that. Preprocessors are smart nowadays. – Jabberwocky Jan 05 '18 at 08:48
  • @Michael Walz That sounds like good news. – Zebrafish Jan 05 '18 at 08:49
  • @Michael Walz I think about this every time I include std::vector in a class definition, I keep thinking that is going to be included in every other cpp that uses it. It's good to hear it's not worth worrying about. – Zebrafish Jan 05 '18 at 08:51
  • Yes, it _is_ included in every cpp that uses it, but no need to worry. – Jabberwocky Jan 05 '18 at 08:52
  • Nope, if you include `::std::vector` in a class definition then every other cpp that uses it will include ``. And no, preprocessor is a plain dumb tool as it was 10, 20 and 30 years ago. However fighting with includes is not really worth it. It is actually better to fight cpps. – user7860670 Jan 05 '18 at 08:54
  • you can hide all class if your own class do not expose internal structures (usually implementation detail). since you don't need these structure outside Physics.h, you can put all related thing in .cpp – apple apple Jan 05 '18 at 09:13
  • you can try using pimpl and just forward declare physics library – fen Jan 05 '18 at 09:22

1 Answers1

0

These two constructs have similar meaning, except that the second one allows you to choose where the memory is created and initilized. I personally would not worry too much aout recursive reader inclusions lues you project is quite big. You are essentially using global variables here for some quite significant shared state, which usually indicates a flow in your design. If your program is multi-threaded and there is no way around the shared state,

I suggest using the third approach and perform some mutual exclusion in the getters and setters (readers-waiter lock seems appropriate) in which case you would need to ensure somehow that the state is only modified through the setter (probably by returning a const reference from the getter.

If you were going to stick with the extern solution and initialisation of these objects in non-trivial (which I assume it is not) you also want to define some sort of initialiser function and make sure that gets called before anything else, in which case you should probably consider writing a Singleton class instead, which is what I would do.