1

I have the following scenario:

header.h:

class A
{
    public:

    class B; // incomplete type

private:
    // is never used outside of source file for A
    std::vector<B> vector_of_bs; // template
}

source1.cpp:

class A::B {}; // defined here

All is good until here. Now if I want to use class A elsewhere it doesn't work:

source2.cpp: uses class A and doesn't compile with

vector(721): error C2036: 'A::B *' : unknown size

while compiling class template member function 'std::vector<_Ty> &std::vector<_Ty>::operator =(const std::vector<_Ty> &)'

in VS2010. How can I link against the template specialisation of std::vector in source1.o?

I also need to use this with declspec(_dllimport)...

Sergey L.
  • 21,822
  • 5
  • 49
  • 75

1 Answers1

2

Standard library containers cannot be instantiated with incomplete types. To do so is undefined behaviour, and in your case produces a clear error. Other implementations would silently accept your code.

To address this issue, boost provides counterparts for the standard library containers that can in fact be instantiated with incomplete types. You could replace std::vector with the boost counterpart to fix your code:

#include <boost/container/vector.hpp>

class A
{
 public: 
    class B; // incomplete type

 private:
    boost::vector<B> vector_of_bs;
};
Community
  • 1
  • 1
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • I don't think that's sufficient. `B` will have to be complete when the copy assignment/destructor/copy constructor etc. are generated, so you'd probably need explicit declarations in the class definition, followed by explicit defaulting in the source file where `B` is complete, similar to pimpls with `unique_ptr`. – T.C. Feb 09 '15 at 19:28