Stack Overflow Asked on December 20, 2021
Given an incomplete type:
struct S;
Then the following declarations are:
S *p; // ok, pointer to incomplete types is allowed
std::deque<S> l; // error, instantiating std::deque with incomplete type is UB
But what about the following declarations?
std::deque<S> *p; // seems to be UB like the previous case,
// but is it ok if p is not used till S is defined?
std::deque<S*> p; // not really sure about this one
Edit: the question used std::list
instead of std::deque
, but that defeats the purpose of the question, since std::list
is explicitly allowed to use incomplete types. std::deque
doesn’t appear to have such permission.
std::deque<S> *p; // seems to be UB like the previous case, // but is it ok if p is not used till S is defined?
That's actually the interesting bit here. Yes, instantiating that container with an incomplete type is not allowed, there is no provision for it. But the question becomes whether or not it's really instantiated. It doesn't have to be, according to the core language.
[temp.inst]
1 Unless a class template specialization has been explicitly instantiated or explicitly specialized, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.
A pointer to a type doesn't require the type to be complete. So this declaration alone is not normally enough to cause an instantiation of a class template, and so it may be premature to determine the requirement of the container is violated here.
Unless of course we take "the completeness of the class type affects the semantics of the program" to include contract violations in the standard library. An implementation could instantiate here, I suppose. I'm not aware of any implementation that does however, so this may not be the desires interpretation.
So to err on to side of caution, I'd deem this UB too.
std::deque<S*> p; // not really sure about this one
This is fine. Whether or not S
is complete, S*
is still a complete object type. I say this because it's not included at
[basic.types]
5 A class that has been declared but not defined, an enumeration type in certain contexts ([dcl.enum]), or an array of unknown bound or of incomplete element type, is an incompletely-defined object type. Incompletely-defined object types and cv void are incomplete types ([basic.fundamental]). Objects shall not be defined to have an incomplete type.
The constraints about the completeness of S
only appear when attempting to use such a pointer in an expressions that does a dereference or pointer arithmetic. But the pointer type itself is still complete. So it's a valid template argument for a container type.
Answered by StoryTeller - Unslander Monica on December 20, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP