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

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

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 выдает ошибку «неполный тип».


person undermind    schedule 01.01.2019    source источник
comment
С какой цепочкой инструментов компилируется (потому что ее рвет как есть с vc++ (19.00.24215.1)? Включите это в свой вопрос.   -  person WhozCraig    schedule 01.01.2019
comment
@WhozCraig Спасибо, я добавил описание. Оказывается, clang это не компилирует.   -  person undermind    schedule 01.01.2019


Ответы (1)


Согласно стандарту, во время неявного создания экземпляра создается только объявление функций-членов, но не их определение.

[temp.inst]/2< /strong> — неявное создание экземпляра специализации шаблона класса вызывает

  • неявное создание экземпляров объявлений, но не определений, неудаленных функций-членов класса, классов-членов, перечислений членов с областью действия, членов статических данных, шаблонов членов и друзей...

но это не говорит то же самое о явных экземплярах. Создается экземпляр всего класса, что означает, что он создает экземпляр определения method(), и в этот момент Foo не завершен.

[temp.explicit]/11 – Явное определение создания экземпляра, которое называет специализацию шаблона класса, явно создает экземпляр специализации шаблона класса и является явным определением создания экземпляра только тех членов, которые были определены в момент создания экземпляра.

clang отклоняет код.

person Jans    schedule 01.01.2019
comment
Действительно, clang его не компилирует (я обновил описание вопроса). Значит, это правильное поведение? - person undermind; 01.01.2019