Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 961
jan.sende Avatar asked Jul 10 '19 17:07

jan.sende


People also ask

Can a vector hold different data types?

A vector will hold an object of a single type, and only a single type.

What does std::vector do?

1) std::vector is a sequence container that encapsulates dynamic size arrays. 2) std::pmr::vector is an alias template that uses a polymorphic allocator. The elements are stored contiguously, which means that elements can be accessed not only through iterators, but also using offsets to regular pointers to elements.

Is std::vector slower than array?

A std::vector can never be faster than an array, as it has (a pointer to the first element of) an array as one of its data members. But the difference in run-time speed is slim and absent in any non-trivial program. One reason for this myth to persist, are examples that compare raw arrays with mis-used std::vectors.

What is incomplete type error in C++?

An incomplete type is a type that describes an identifier but lacks information needed to determine the size of the identifier. An incomplete type can be: A structure type whose members you have not yet specified. A union type whose members you have not yet specified.


1 Answers

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]).

like image 56
eerorika Avatar answered Sep 21 '22 05:09

eerorika