简体   繁体   中英

Why does std::vector work with incomplete types in class definitions?

The following question came up:

The c++ standard seems to say, that std::vector requires a complete type to work. (See https://en.cppreference.com/w/cpp/container/vector ) Then, why does the following code still compile?

#include <vector>

struct parent;

struct child
{
    std::vector<parent> parents; //parent is incomplete here!
};

struct parent
{
    std::vector<child> children;
};

This seems counterintuitive. If std::vector requires a complete type, then std::vector<parent> should not compile because only its forward declaration is known inside the class definition of child .

  • Is this behaviour something special about class definitions?
  • Did I get it wrong, and std::vector does not require a complete type?
  • Or, is this just a fluke? In that technically this isn't allowed, but it works for all implementations anyways...

EDIT

There seems to be a difference between c++11 and c++17. I would like to understand the c++11 version.

Standard says (draft N3690; this is post C++11, pre C++14):

[res.on.functions]

1 In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++standard library depends on components supplied by a C++program. If these components do not meet their requirements, the Standard places no requirements on the implementation .

2 In particular, the effects are undefined in the following cases:

— if an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically allowed for that component.

Given that standard places no requirements, and effects are undefined (as far as I can tell, this is same as undefined behaviour), there is no expectation for the instantiation to "not work" any more than there is expectation for it to (appear to) "work".


Since C++17, the requirement was relaxed and std::vector does not require the value type to be complete, if used with appropriate allocator (the default allocator is appropriate). (This freedom does not extend to using all member functions; they have additional requirements).

Standard quote (current draft):

[vector.overview]

An incomplete type T may be used when instantiating vector if the allocator meets the allocator completeness requirements. T shall be complete before any member of the resulting specialization of vector is referenced.

[allocator.requirements.completeness]

If X is an allocator class for type T, X additionally meets the allocator completeness requirements if, whether or not T is a complete type:

  • X is a complete type, and
  • all the member types of allocator_traits other than value_type are complete types.

[default.allocator]

All specializations of the default allocator meet the allocator completeness requirements ([allocator.requirements.completeness]).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM