I have a class with a vector
member variable whose T
is declared, but not defined. This can be a problem if no destructor for the class is defined, since the compiler might pick some other translation unit to generate the destructor in. If that TU doesn't have a definition for T
, compilation fails.
struct undefined;
struct S
{
S(int);
std::vector<undefined> v;
};
int main()
{
S s(42); // fails in ~vector(), `undefined` is undefined
}
To work around this problem, I usually add a defaulted destructor as an anchor in the file that implements the class, which has access to the definition.
struct undefined;
struct S
{
S(int);
~S(); // implemented in another TU as `S::~S() = default;`
std::vector<undefined> v;
};
int main()
{
S s(42); // ok
}
I'm trying to do the same thing with a derived class that inherits the base class' constructor:
#include <vector>
struct undefined;
struct base
{
base(int);
};
struct derived : base
{
using base::base;
~derived();
std::vector<undefined> v;
};
int main()
{
derived d(1); // fails in ~vector(), `undefined` is undefined
}
If I change derived
to not inherit the constructor, compilation succeeds:
#include <vector>
struct undefined;
struct base
{
base(int);
};
struct derived : base
{
//using base::base; <--- note
derived(int);
~derived();
std::vector<undefined> v;
};
int main()
{
derived d(1); // ok
}
What's really confusing to me is that clang says this:
stl_vector.h:336:35: error: arithmetic on a pointer to an incomplete type 'undefined'
[blah]
a.cpp:12:14: note: in instantiation of member function 'std::vector<undefined>::~vector' requested here
using base::base;
^
It sounds like using base::base
is also bringing in something that's destroying the vector
, but I have no idea what. I've tried deleting copy/move constructors/operators in both classes, but the error remains. Both g++ and Visual C++ fail with similar errors.
What's going on?
vector<T>
has to know the size of it's elements and that can't be determined from the incomplete type. You can have a vector of pointers to an incomplete type. – Phenacitevector
can most definitely use an incomplete type as long as you don't do anything with it, see this and this. – Willodeanwilloughbyderived(int v) : base(v) = default;
(not valid syntax but I hope you get the idea) - this means that the compiler has to generate code for the constructor, and that means also generating code for the vector's destructor, in case an exception is thrown from the constructor. – Insipidstruct undefined
? – Odellestruct S
never need the definition ofundefined
itself, it's used internally byS
. – Willodeanwilloughby