Как можно использовать неполный тип в качестве параметра шаблона для вектора здесь?

TIL следующая программа является законной и ничего:

#include <vector>

struct Bar;

struct Foo
{
    using BarVec = std::vector<Bar>::size_type;
};

struct Bar {};

int main()
{
   Foo f;
}

Как? Bar является неполным, поэтому компилятор не знает, что такое std::vector<Bar> или он содержит член size_type или что элемент size_type является типом.

Единственное объяснение, которое я могу придумать, заключается в том, что любая гипотетическая специализация (предположительно) должна быть уже в пределах возможностей, чтобы заставить size_type использовать значение, отличное от значения, указанного в определении базового шаблона, и size_type не является зависимым именем (оба фактора, способствующие определенности компилятора).

Какое юридическое обоснование здесь?

Ответ 1

Я думаю, что на практике это может работать, но из того, что я могу сказать, выглядит как поведение undefined. Из проекта стандарта С++ 11 17.6.4.8 [res.on.functions]:

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

[...]

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

Хотя создание экземпляра компонента шаблона не похоже на четко определенный термин.

Я пришел к этому через дефект LWG 611, который добавил:

если это специально не разрешено для компонента.

до конца пули выше, поэтому он теперь читает:

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

как исключение для shared_ptr, поскольку приведенная цитата противоречила этой цитате из 20.6.6.2 [util.smartptr.shared]:

Параметр шаблона T shared_ptr может быть неполным.

Также см. N4371: Минимальная поддержка неполного типа для стандартных контейнеров, версия 2.

Ответ 2

Это то, что я собрал из стандартного

§14.3.1 Аргументы типа шаблона

1 Аргумент шаблона для параметра шаблона, который является типом, должен быть идентификатором типа 2... [Примечание: Аргумент типа шаблона может быть неполным типом]

§14.6 Разрешение имен

Зная, какие имена являются именами типов, можно проверить синтаксис каждого шаблона. Диаграмма не должна выдаваться для шаблона, для которого может быть создана действительная специализация. Если для шаблона не может быть создана действительная специализация, и этот шаблон не создается, шаблон плохо сформирован, не требуется диагностика. Если для каждой допустимой специализации вариационного шаблона требуется пустой пакет параметров шаблона, шаблон плохо сформирован, диагностика не требуется. Если гипотетическое создание шаблона сразу после его определения будет плохо сформировано из-за конструкции, которая не зависит от параметра шаблона, программа плохо сформирована; диагностика не требуется. Если интерпретация такой конструкции в гипотетическом экземпляре отличается от интерпретации соответствующей конструкции при любой фактической инстанцировании шаблона, программа плохо сформирована; диагностика не требуется. [Примечание: это может произойти в ситуациях, в том числе: - тип, используемый в независящем имени, является неполным в точке, где шаблон определен, но завершен в точке, в которой выполняется инстанцирование, или
-...

Итак, в вашем примере Bar был неполным после объявления Foo, но он был завершен к моменту создания экземпляра Foo