Тип параметра шаблона рассматривается компилятором как завершенный, но его определение пока не видно

Предположим, у меня есть следующий фрагмент кода:

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 отклоняет код.

Другие вопросы по тегам