Страницы

Поиск по вопросам

среда, 22 января 2020 г.

Необходимость template<> для объявления полной специализации шаблонного класса

#cpp #история


Почему для объявления полной специализации шаблонного класса используется синтаксис
template<>? Зачем он нужен, если можно использовать просто название класса со специализируемыми
типами?
    


Ответы

Ответ 1



В С++ синтаксис template<> class SomeClass<аргументы> объявляет совершено новую сущность - явную специализацию шаблонного класса. Хоть явная специализация и имеет связь с "главным" шаблоном, ее содержимое (определение) является совершенно независимым от главного шаблона. А синтаксис class SomeClass<аргументы> просто ссылается на уже существующую сущность - на специализацию какого-то уже объявленного шаблонного класса SomeClass для данного набора аргументов. У этих синтаксисов совершено разные цели: объявление новой сущности vs. ссылка на уже ранее объявленную сущность. Также, когда речь идет об объявлениях специализаций членов классов, наличие или отсутствие template <> также приводит к серьезным различиям в интерпретации таких объявлений (хотя суть различия остается та же). См. https://ru.stackoverflow.com/a/934161/182825 Тут можно попытаться изобрести какой-то набор автоматических правил, которые, возможно, позволили бы компилятору самому разобраться, что именно мы хотим сделать в каждом конкретном контексте. Однако в С++ традиционно введение новых сущностей делается явно и для этого выделен отдельный синтаксис объявления. Для явных специализаций этот отдельный синтаксис - это именно синтаксис начинающийся с template <>.

Ответ 2



Изначально полную специализацию действительно объявляли без template<>, т.е. template struct A { }; struct A { }; , однако в стандарт вошёл именно вариант с template<> из-за неоднозначностей (ambiguities) в более сложных случаях полных специализаций. Например: // №1 template struct A { template struct B { static int x; }; }; // №2 template<> template struct A::B { static unsigned x; }; // №3 template<> template<> unsigned A::B::x; // №4 template<> struct A { template struct B { static long x; }; }; // №5 template<> long A::B::x; Здесь №2 - специализация члена шаблонного класса A для типа unsigned, №4 - полная специализация шаблонного класса A для типа long, №3 - специализация члена шаблонного класса A::B для типа unsigned, №5 - то же, что и №3 для типов long, но так как присутствует полная специализация №4, в №5 только 1 template<> в отличие от 2 template<> в №3. Если бы template<> отсутствовали, то специализации №3 и №5 были бы неотличимы.

Комментариев нет:

Отправить комментарий