Тип параметра шаблона рассматривается компилятором как завершенный, но его определение пока не видно
Предположим, у меня есть следующий фрагмент кода:
template <class T>
class Bar
{
// static_assert(sizeof(T) > 0); // (1)
public:
void method()
{
static_assert(sizeof(T) > 0); // (2)
}
};
class Foo; // (3)
template class Bar<Foo>; // (4)
class Foo{}; // (5)
Если мы раскомментируем строку (1), мы получим ошибку во время компиляции "неполный тип T", и это будет ясно: class Bar
инстанцирование запускается с помощью (4), и в этот момент class Foo
только объявлено заранее (3) и еще не определено (5).
Но если строка (1) закомментирована, то этот код компилируется без ошибок, и это меня смущает: (4) является явным определением экземпляра шаблона, и это заставляет компилятор генерировать void method()
код и строка (2) также должны генерировать ту же ошибку, так как определение Foo
сделано позже в (5).
Что мне не хватает, почему компилируется код из фрагмента?
ОБНОВЛЕНИЕ: Код компилируется в GCC 8.2.0 и MSVC 19.16.27025.1, но в Clang 7.0.0 выдает ошибку "неполного типа".
1 ответ
Согласно стандарту, во время неявной реализации создается только объявление функций-членов, но не их определение.
[temp.inst] / 2 - неявная реализация специализации шаблона класса вызывает
- неявное создание деклараций, но не определений, неотчеркнутых функций-членов класса, классов-членов, перечислений членов в области действия, статических элементов данных, шаблонов элементов и друзей...
но это не говорит то же самое о явных экземплярах. Целый класс создается, что означает, что он создает определение method()
и в этот момент Foo
не завершено
[temp.explicit] / 11 - Явное определение экземпляра, которое называет специализацию шаблона класса в явном виде, создает экземпляр специализации шаблона класса и является явным определением экземпляра только тех членов, которые были определены в момент создания экземпляра.
Clang отклоняет код.