Jump to content

Частичная специализация шаблона

Частичная специализация шаблона — это особая форма специализации шаблона класса . Обычно используемый применительно к C++ языку программирования , он позволяет программисту специализировать только некоторые аргументы шаблона класса, в отличие от явной полной специализации, при которой предоставляются все аргументы шаблона.

Шаблоны и специализация

[ редактировать ]

Шаблоны классов на самом деле являются метаклассами: это частичные абстрактные типы данных, которые предоставляют компилятору инструкции о том, как создавать классы с соответствующими элементами данных. Например, стандартные контейнеры C++ представляют собой шаблоны классов. Когда программист использует вектор, он создает его экземпляр с определенным типом данных, например, int, string или double. Каждый тип вектора приводит к созданию отдельного класса в объектном коде компилятора, каждый из которых работает со своим типом данных. Этот процесс называется мономорфизацией дженериков.

Если известно, что шаблон класса будет довольно часто использоваться с определенным типом данных и этот тип данных допускает некоторую оптимизацию (например, смещение битов при использовании целых чисел вместо умножения или деления на 2), можно ввести специализированный шаблон класса с некоторыми из предустановленных параметров шаблона. Когда компилятор видит такой шаблон класса, созданный в коде, он обычно выбирает наиболее специализированное определение шаблона, соответствующее созданию экземпляра. Таким образом, явная полная специализация (та, где указаны все аргументы шаблона) будет предпочтительнее частичной специализации, если все аргументы шаблона совпадают.

Частичная специализация

[ редактировать ]

Шаблоны могут иметь более одного типа параметров. Некоторые старые компиляторы позволяют специализировать только все параметры шаблона или ни одного из них. Компиляторы, поддерживающие частичную специализацию, позволяют программисту специализировать некоторые параметры, оставляя другие универсальными.

Предположим, существует KeyValuePair класс с двумя параметрами шаблона, как показано ниже.

template <typename Key, typename Value>
class KeyValuePair {};

Ниже приведен пример класса, который определяет явную полную специализацию шаблона KeyValuePair путем объединения целых чисел со строками. Тип класса сохраняет то же имя, что и исходная версия.

template <>
class KeyValuePair<int, std::string> {};

Следующий пример — частичная специализация KeyValuePair с тем же именем, что и исходная версия, и одним специализированным параметром шаблона.

template <typename Key>
class KeyValuePair<Key, std::string> {};

Следующий пример класса KeyStringPair является производным от оригинала KeyValuePair с новым именем и определяет частичную специализацию шаблона. В отличие от явной специализации, описанной выше, только Value параметр шаблона суперкласса является специализированным, а параметр шаблона Key остается универсальным.

template <typename Key>
class KeyStringPair : public KeyValuePair<Key, std::string> {};

Не имеет значения, какие параметры шаблона являются специализированными, а какие остаются общими. Например, следующее также является допустимым примером частичной специализации исходного KeyValuePair сорт.

template <typename Value>
class IntegerValuePair : public KeyValuePair<int, Value> {};

Предостережения

[ редактировать ]

Шаблоны C++ не ограничиваются классами — их также можно использовать для определения шаблонов функций . Хотя шаблоны функций могут быть полностью специализированными, они не могут быть частично специализированными, независимо от того, являются ли они шаблонами функций-членов или шаблонами функций, не являющихся членами. Это может быть полезно для авторов компиляторов, но влияет на гибкость и детализацию того, что могут делать разработчики. [1] Но шаблоны функций могут быть перегружены , что дает почти тот же эффект, что и частичная специализация шаблона функции. [2] Следующие примеры приведены для иллюстрации этих положений.

// legal: base function template
template <typename ReturnType, typename ArgumentType>
ReturnType Foo(ArgumentType arg);

// legal: explicit/full function template specialization
template <>
std::string Foo<std::string, char>(char arg) { return "Full"; }

// illegal: partial function template specialization of the return type
//          function template partial specialization is not allowed
// template <typename ArgumentType>
// void Foo<void, ArgumentType>(ArgumentType arg);

// legal: overloads the base template for a pointer argument type
template <typename ReturnType, typename ArgumentType>
ReturnType Foo(ArgumentType *argPtr) { return "PtrOverload"; }

// legal: base function name reused. Not considered an overload. ill-formed: non-overloadable declaration (see below)
template <typename ArgumentType>
std::string Foo(ArgumentType arg) { return "Return1"; }

// legal: base function name reused. Not considered an overload. ill-formed: non-overloadable declaration (see below)
template <typename ReturnType>
ReturnType Foo(char arg) { return "Return2"; }

Обратите внимание, что в приведенном выше примере, хотя последние два определения функции Foo являются законными C++, они считаются неправильно сформированными в соответствии со стандартом, поскольку являются неперегружаемыми объявлениями. [3] Это связано с тем, что определение перегрузки функции учитывает только имя функции, список типов параметров и охватывающее пространство имен (если таковое имеется). Он не учитывает тип возвращаемого значения. [4] Однако эти функции по-прежнему можно вызывать, явно указав компилятору сигнатуру, как показано в следующей программе.

// note: to be compiled in conjunction with the definitions of Foo above

int main(int argc, char *argv[])
{
    char c = 'c';
    std::string r0, r1, r2, r3;
    // let the compiler resolve the call
    r0 = Foo(c);
    // explicitly specify which function to call
    r1 = Foo<std::string>(c);
    r2 = Foo<std::string, char>(c);
    r3 = Foo<std::string, char>(&c);
    // generate output
    std::cout << r0 << " " << r1 << " " << r2 << " " << r3 << std::endl;
    return 0;
}

//expected output:
Return1 Return2 Full PtrOverload
  1. ^ Александреску, Андрей (1 февраля 2001 г.). Современный дизайн на C++ . Эддисон Уэсли. стр. 23. ISBN  0-201-70431-5 .
  2. ^ Саттер, Херб (июль 2001 г.). «Почему бы не специализироваться на шаблонах функций?» . Журнал пользователей C/C++ . 19 (7) . Проверено 7 декабря 2014 г.
  3. ^ «ISO/IEC JTC1 SC22 WG21 N 3690: Языки программирования — C++» (PDF) . ИСО. 15 мая 2013 г. с. 294 . Проверено 16 октября 2016 г. 13.1. Перегружаемые объявления [over.load] Не все объявления функций могут быть перегружены. Здесь указаны те, которые нельзя перегрузить. Программа считается неправильной, если она содержит два таких неперегружаемых объявления в одной области действия.
  4. ^ «ISO/IEC JTC1 SC22 WG21 N 3690: Языки программирования — C++» (PDF) . ИСО. 15 мая 2013 г. стр. 294–296 . Проверено 16 октября 2016 г. 13.1 Перегружаемые объявления [over.load]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 546332a5fe5918a0d660c5d060c4f2c8__1712775540
URL1:https://arc.ask3.ru/arc/aa/54/c8/546332a5fe5918a0d660c5d060c4f2c8.html
Заголовок, (Title) документа по адресу, URL1:
Partial template specialization - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)