Подтвердить что ты не робот

Как я могу объявить вектор-член одного класса?

Почему на земле работает следующий фрагмент кода?

struct A {
    std::vector<A> subAs;
};

A - неполный тип, верно? Если бы был вектор A * s, я бы понял. Но здесь я не понимаю, как это работает. Кажется, это рекурсивное определение.

4b9b3361

Ответ 1

Этот paper был принят в С++ 17, который позволяет неполные типы, которые будут использоваться в некоторых контейнерах STL. До этого было Undefined Поведение. Процитировать из статьи:

Основываясь на обсуждении собрания Иссакуа, мы достигли консенсус для продолжения * с подходом - "Контейнеры неполных Типы", но ограничивайте область std::vector, std::list и std::forward_list, как первый шаг.

А что касается изменений в стандарте (акцент мой):

Неполный тип T может использоваться при создании экземпляра vector, если распределитель удовлетворяет требованиям-комплектности распределителя (17.6.3.5.1). T должно быть полным до того, как какой-либо член специализация вектора.

Итак, у вас есть это, если вы оставите по умолчанию std::allocator<T> на месте при создании экземпляра std::vector<T, Allocator>, тогда он всегда будет работать с неполным типом T в соответствии с документом; в противном случае это зависит от того, что ваш Allocator является исполняемым с неполным типом T.


A - неполный тип, верно? Если бы был вектор A * s, я бы понял. Но здесь я не понимаю, как это работает. Кажется, это рекурсивное определение.

Там нет рекурсии. В чрезвычайно упрощенной форме он похож на:

class A{
    A* subAs;
};

Технически, кроме size, capacity и, возможно, allocator, std::vector нужно только удерживать указатель на динамический массив A, который управляет через его распределитель. (И размер указателя известен во время компиляции.)

Итак, реализация может выглядеть так:

namespace std{

    template<typename T, typename Allocator = std::allocator<T>>
    class vector{

        ....

        std::size_t m_capacity;
        std::size_t m_size;
        Allocator m_allocator;
        T* m_data;
    };

}