I'm writing a library. Its layout looks something akin to this:
/////////
// A.h //
/////////
#include <vector>
class B;
class A
{
std::vector<B> Bs;
public:
...
};
/////////
// B.h //
/////////
class B
{
...
}
///////////
// A.cpp //
///////////
#include "A.h"
#include "B.h"
// Implementation of A follows
...
///////////
// B.cpp //
///////////
#include "B.h"
// Implementation of B follows
...
/////////////
// MyLib.h //
/////////////
#include "A.h"
As you can see, the only type accessible from the outside is supposed to be A
, that's why B
is declared as an incomplete type in A.h
. The library itself compiles fine, but when it comes to using it in a program, the compiler issues errors like: invalid use of incomplete type B
when I try to create an object of type A
. These errors point to the vector
header, specifically, to the std::vector
's destructor, which apparently needs to know the size of the type it holds to deallocate the internal storage properly. What I think is happening is that the compiler is trying to instantiate std::vector<B>::~vector
in my program, which can't succeed for aforementioned reasons. However, there are symbols for std::vector<B>::~vector
in the library's binary, so I could do without instantiating it in the program. I'm looking for a way to tell that to the compiler. I've already tried changing MyLib.h
to something like this:
/////////////
// MyLib.h //
/////////////
#include "A.h"
extern template class std::vector<B>;
This unfortunately doesn't work, because extern
applies only to the code generation stage of the compilation, and the compiler still reports errors while parsing. I thought that maybe the compiler is trying to instantiate std::vector<B>::~vector
because A
has an implicit destructor, so I tried implementing a destructor manually like this:
/////////
// A.h //
/////////
#include <vector>
class B;
class A
{
std::vector<B> Bs;
~A();
public:
...
};
///////////
// A.cpp //
///////////
#include "A.h"
#include "B.h"
A::~A() {}
// Further implementation of A follows
...
This doesn't help either, the compiler is still trying to instantiate std::vector<B>::~vector
, even though it shouldn't ever be invoked outside the library code now. Is there a different way to achieve what I want or would it be best to choose a different method of information hiding for B
?