Рассмотрим следующий пример.
template <typename A> struct S
{
A a;
void foo() {}
};
template <typename T> void bar()
{
S<void> *p = 0;
}
template <typename T> void baz()
{
S<void>{}.foo();
}
template <typename T> void qux()
{
S<void> s{};
}
int main()
{
}
Шаблоны функций bar
, baz
и qux
намеренно оставлены неинстанцированными.
Определение baz
не удаетсякомпилировать в GCC и Clang по «очевидной» причине - S<void>
является недопустимой специализацией S
.Однако какое правило языка работает в этом случае?
С одной стороны, S<void>
не зависит от параметров шаблона baz
, доступ к элементу требует его завершения,который запускает создание экземпляра S<void>
, что не удается.Диагностика обязательна.
С другой стороны, у нас есть общее правило: «Если не может быть сгенерирована действительная специализация для неинстанцированного шаблона, код некорректно сформирован».Это делает определение baz
плохо сформированным.Тем не менее, никакой диагностики не требуется.
В частности, правильно ли я в своем предположении (как выражено в # 1), что приведенная выше ссылка на S<void>
от неинстанцированного baz
требует создания экземпляра S<void>
?Предположение подтверждается тем фактом, что оба компилятора с радостью принимают определение bar
, которое не создает экземпляр S<void>
.
Однако вышеупомянутые компиляторы по-разному трактуют qux
- Кланг жалуется,в то время как GCC принимает это без каких-либо жалоб.Это ошибка в одном из компиляторов?Требуется ли в этом случае диагностика?Или я ошибаюсь, полагая, что № 1 здесь на работе?Если № 2 является основой для диагностики, то разница между компиляторами является приемлемой.