Std::vector в прямом объявленном типе

Следующий код, похоже, корректно работает с Clang++ и GCC:

#include <vector>

class A {
private:
    int i;
    std::vector<A> children;
public:
    A& add();
};

A& A::add() { children.emplace_back(); return children.back(); }

int main() {
    A a;
    A& a2 = a.add();
}

Когда объявлен член данных std::vector<A>, A по-прежнему является неполным. То же самое, когда использование std::vector<B> и B было объявлено только с помощью class B;. Он должен работать с std::vector, поскольку он содержит только указатель на A.

Гарантировано ли это работать, или undefined поведение?

Ответ 1

Это поведение undefined в С++ 14 и более ранних версиях; хорошо определен в С++ 17 (если это 17).

[res.on.functions]/p2, bullet 2.7:

В частности, эффекты undefined в следующих случаях:

  • [...]
  • если неполный тип (3.9) используется в качестве аргумента шаблона при создании экземпляра компонента шаблона, если это специально не разрешено для этот компонент.

В С++ 14 и более ранних версиях std::vector не "специально разрешает" это. Таким образом, поведение undefined.

Для С++ 17, N4510, принятого на заседании Комитета в мае 2015 года, ослабляет это правило для vector, list и forward_list.

Ответ 2

В соответствии с разделом "Параметры шаблона" из cppreference.com это может работать (в зависимости от фактического использования контейнера) в С++ 17, но не в С++ 14 и ранее. Возможно, вы используете версии компиляторов, которые реализуют эту часть стандарта С++ 17.