Is an incomplete vector allowed if no member functions are called? If yes, then when?
Suppose I have an incomplete type
// in foo.hh
struct Hidden;
which I want to use as the element type std::vector
. Using union
, I can "defer" queries to the constructor (s) and destructor std::vector
to the union constructor (s) / destructor implementation.
// in foo.hh
struct Public {
union Defer {
std::vector<Hidden> v;
Defer();
// add copy/move constructor if needed
~Defer();
} d;
};
Now I can use Public
by including only foo.hh
and linking to the file (s) implementing Public::Defer::Defer()
and Public::Defer::~Defer()
. Only those who need access to the full definition Hidden
.
Is this legal C ++? If yes, then when?
Background: Question that came up in my answer to another question .
source to share
std::vector<T>
Incomplete type creation was T
undefined behavior until C ++ 14. In C ++ 17, this limitation is somewhat relaxed:
[vector.overview] / 3 An incomplete type
T
may be used on instantiationvector
if the allocator satisfies the completeness of the allocator requirement 17.6.3.5.1.T
must be completed before any element of the resulting specialization can be specifiedvector
.
(Note: The default allocator std::allocator
meets these completeness requirements.)
My reading is that as of C ++ 17 it is legal for a translation unit to include your header (the one that forward-declares Hidden
and defines Public
) and define a variable Public pub;
- but not to actually use any members pub.d.v
. Prior to C ++ 17, simply including the header would already cause undefined behavior.
source to share