Частичная специализация шаблона — механизм языка программирования С++, предназначенный для специализации обобщённых шаблонных классов под конкретные задачи или под конкретное подмножество своих параметризованных типов данных [1] . По мнению американского учёного и создателя С++ Б. Страуструпа специализация шаблонов является эффективным средством предотвращения неконтролируемого разрастания объёмов кода при активном использовании инструментария классов-шаблонов даже при разработке программных проектов умеренного размера. Это связывают с тем, что она не позволяет генерировать избыточные реплики кода под каждый конкретный тип данных, заменяя их более обобщёнными фрагментами кода и вдобавок сокращая время компиляции и компоновки конечного продукта [2] .
Содержание
- Содержание
- Явная полная специализация [ править | править код ]
- Частичная специализация [ править | править код ]
- Пример [ править | править код ]
- 2 ответа 2
- Решение
- Другие решения
Содержание
Явная полная специализация [ править | править код ]
В С++ явная специализация параметризованного типа данных (шаблона) осуществляется через создание дополнительного класса-шаблона в котором входные параметры первичного класса полностью или частично переопределяются конкретными типами данных [1] [3] .
Синтаксис такого переопределения выглядит следующим образом [4] :
Отмечается, что определения типов данных, содержащиеся в первичном классе, никогда не используются для конкретизации членов его частичной специализации. Однако, кодовая имплементация специализированных версий первичного класса никак с ним не связана и может содержать в себе набор членов, которые не имеют ничего общего с членами первичного класса [4] .
На этапе генерирования кода компилятор при поиске подходящего шаблона частично упорядочивает имеющиеся у него варианты специализации первичного класса и выбирает из них наиболее подходящий. Если таковой отсутствует, то компилятором генерируется сообщение об ошибке [4] .
Частичная специализация [ править | править код ]
Частичная специализация шаблона класса определяется как некая конфигурация параметров первичного класса, которая служит аргументом специализированной реализации. Примером такой специализации может служить любой класс-контейнер, реализованный для хранения объектов-указателей [2] [5] :
В этом случае аргумент-параметр шаблона не является выражением, переданным шаблону в качестве аргумента, а выводится из конструкции аргумента на базе объявленного шаблона первичного класса [2] .
Частичная специализация отдельных методов параметризованного класса-шаблона не допускается [1] , помимо этого для частичной специализации не предусмотрено использование параметров по умолчанию [5] .
Пример [ править | править код ]
Гибкое использование частичной специализации шаблонов позволяет эффективно выполнять некоторые нетривиальные типы вычислений. Например, достаточно несложная композиция классов может помочь с вычислением структуры (количества размерностей) многомерного массива с элементами заранее неизвестного типа [5] :
Здравствуйте люди добрые! Решаю задачку по плюсам, суть такая, что не могу написать специализацию шаблона функции — компилятор ругается. Суть задачки — при передачи числового массива (и кол-ва элементов, конечно) тупо найти наибольшее и вернуть, но доп. условие — эта самая специализация класса, чтобы при передаче массива указателей на char вернуть указатель на самую длинную строку.
Ругается компилятор следующим образом:
8_6.cpp:20:20: ошибка: идентификатор шаблона «maxn» для «char* maxn(const char**, int)» не соответствует никакой декларации шаблона template char * maxn(const char * [], int); // специализация ^
8_6.cpp:19:25: замечание: candidate is: template T maxn(const T*, int) template T maxn(const T [], int); // шаблон
Подскажите что не так делаю, ибо только осваиваю шаблоны эти, перерыл, а что не так — не пойму, хоть убей..
2 ответа 2
Тип const char *[] соответствует типу T[] при T == const char * . Т.е. тип const char *[] — это массив с неконстантными элементами. Тип const char *[] никак не может соответствовать типу const T[] ни при каком T .
У вас в главном шаблоне параметр объявлен именно как const T[] , а в явной специализации указан параметр типа const char *[] . Компилятор никак не сможет увидеть в этом явную специализацию главного шаблона, ибо не существует такого T , при котором const T[] будет соответствовать const char *[] .
Если вы хотите, чтобы такое соответствие было возможным, специализация должна объявлять свой параметр как массив с константными элементами: const char *const [] . При этом первый const опционален (он входит внутрь T ).
Корректные варианты объявления явных специализаций данного шаблона могут выглядеть так
Получение следующих ошибок компиляции:
Ошибка 1: Есть ли обходной путь для этого? Разве специализация вообще не разрешена для области без пространства имен (в данном случае это класс)?
Ошибка 2: Мне известно о том, что частичная специализация шаблонов функций не допускается. Тем не менее, я не понимаю, как это частичная специализация? Любое решение?
Примечание. Если функции не являются методами-членами класса, код компилируется нормально.
Решение
В C ++ 11 [temp.expl.spec] / 2 требует, чтобы явные специализации шаблонных функций происходили в области пространства имен.
Явная специализация должна быть объявлена в пространстве имен, включающем специализированный шаблон. […]
Из-за этого вы должны использовать
Что сказал DR CWG 727 с тех пор был применен, и clang (8.0.0+) и MSVS (2015 обновление 3+) скомпилируют код как новую формулировку для [Temp.expl.spec] / 2 является
Явная специализация может быть объявлена в любой области, в которой может быть определен соответствующий первичный шаблон ([namespace.memdef], [class.mem], [temp.mem]).
Это было принято для C ++ 17, но также было задним числом применено к C ++ 14
Другие решения
Вероятно, дублирующий вопрос, но ответ короткий:
Выполняйте специализацию вне определения класса, т.е.
Источник: