шаблонные параметры шаблонов c
Шаблоны и шаблонные функции в C++. Введение
Шаблонные функции
Давайте рассмотрим простой пример. Допустим, у нас есть функция, которая меняет местами значения двух переменных типа int:
Теперь, допустим, у нас в функции main так же есть две переменные типа double, значения которых тоже нужно обменять. Функция для обмена значений двух переменных типа int нам не подойдет. Напишем функцию для double:
И теперь перепишем main:
Как видите, у нас алгоритм абсолютно одинаковый, отличаются лишь типы параметров и тип переменной temp. А теперь представьте, что нам еще нужны функции для short, long double, char, string и еще множества других типов. Конечно, можно просто скопировать первую функцию, и исправить типы на нужные, тогда получим новую функцию с необходимыми типами. А если функция будет не такая простая? А вдруг потом еще обнаружится, что в первой функции была ошибка? Избежать всего этого можно, например, «шаманством» с препроцессором, но это нам ни к чему, нам помогут шаблоны.
Для начала, заглянем в википедию и посмотрим, что же такое шаблоны:
Шабло́ны (англ. template) — средство языка C++, предназначенное для кодирования обобщённых алгоритмов, без привязки к некоторым параметрам (например, типам данных, размерам буферов, значениям по умолчанию).
https://ru.wikipedia.org/wiki/Шаблоны_C++
Итак, описание шаблона начинается с ключевого слова template за которым в угловых скобках (« ») следует список параметров шаблона. Далее, собственно идет объявление шаблонной сущности (например функция или класс), т. е. имеет вид:
Теперь давайте напишем шаблонную функцию my_swap. Исходя из упомянутой выше структуры объявления шаблона следует, что наша функция будет выглядеть так:
typename в угловых скобках означает, что параметром шаблона будет тип данных. T — имя параметра шаблона. Вместо typename здесь можно использовать слово class: template В данном контексте ключевые слова typename и class эквивалентны (лично мне больше нравится typename, а кому-то class). Далее, в тексте шаблона везде, где мы используем тип T, вместо T будет проставляться необходимый нам тип.
теперь давайте напишем функцию main:
Таким образом, если мы инстанцируем этот шаблон три раза с разными типами, то компилятор создаст три разные функции
Вывод типа шаблона исходя из параметров функции
На самом деле, мы можем вызвать функцию my_swap не указывая тип в угловых скобках. В ряде случаев компилятор может это сделать за вас.
рассмотрим вызов функции без указания типа:
Наша шаблонная функция принимает параметры типа T&, основываясь на шаблоне, компилятор видит, что Вы передаете в функцию аргументы типа int, поэтому может самостоятельно определить, что в данном месте имеется ввиду функция my_swap с типом int. Это deducing template arguments. Теперь давайте напишем пример посложнее. Например, программу сортировки массива(будем использовать сортировку «пузырьком»). Естественно, что алгоритм сортировки один и тот же, а вот типы элементов в массиве будут отличаться. Для обменивания значений будем использовать нашу шаблонную функцию my_swap. Приступим:
Source arrays: 10 5 7 3 4 7.62 5.56 38 56 9 Sorted arrays: 3 4 5 7 10 5.56 7.62 9 38 56
Как видите, компилятор сам генерирует out_array для необходимого типа. Так же он сам генерирует функцию bubbleSort. А в bubbleSort у нас применяется шаблонная функция my_swap, компилятор сгенерирует и её код автоматически. Удобно, не правда ли?
Введение в шаблонные классы
Шаблонными могут быть не только функции. Рассмотрим шаблонные классы. Начнем с простого примера. Мы добавим в наш предыдущий код функцию, которая будет искать максимум и минимум в массиве. При создании функции «упираемся» в проблему — как вернуть два указателя? Можно передать их в функцию в качестве параметров, а можно вернуть объект, который будет содержать в себе два указателя. Первый вариант при большом кол-ве возвращаемых значений приведет к заваливанию функции параметрами, поэтому я предлагаю сделать структуру:
А какого же типа будут указатели? Можно сделать их void*, но тогда придется постоянно кастовать их к нужному типу, и код станет похож на «Доширак». А что, если сделать эту структуру шаблонной? Попробуем:
Теперь компилятор при виде кода my_pointer_pair сам сгенерирует нам код структуры с соответствующими типами. В данном примере указатели у нас будут одинакового типа, но структуру мы сделаем такой, чтобы типы указателей могли быть разными. Это может быть полезно в других примерах (в данном случае я просто хотел показать, что у шаблона может быть не только один параметр).
Компилятор не будет автоматически определять типы для шаблона класса, поэтому необходимо их указывать самостоятельно.
Теперь давайте напишем код шаблонной функции для поиска максимума и минимума:
Теперь мы можем вызывать данную функцию:
Для классов мы должны явно указывать параметры шаблона. В стандарте C++11, устаревшее ключевое слово auto поменяло свое значение и теперь служит для автоматического вывода типа в зависимости от типа инициализатора, поэтому мы можем написать так:
Предлагаю написать еще одну функцию, которая будет выводить объект my_pointer_pair в стандартный поток вывода:
Теперь соберем всё воедино:
Arrays: 10 5 7 3 4 7.62 5.56 38 56 9 min = 3 max = 10 min = 5.56 max = 56
Шаблоны и STL
В комплекте с компилятором Вам предоставляется стандартная библиотека шаблонов (Standart Template Library). Она содержит множество шаблонных функций и классов. Например, класс двусвязного списка(list), класс «пара» (pair), функция обмена двух переменных(swap), функции сортировок, динамически расширяемый массив(vector) и т.д. Всё это — шаблоны и Вы можете их использовать. Для небольшого примера возьмем std::vector:
Заметьте, когда писали std::vector, авторы понятия не имели, элементы какого типа Вы будете хранить.
Шаблоны это слишком большой и мощный инструмент и описать всё в одной статье не представляется возможным. Это было лишь небольшое введение в мир шаблонов. Углубляясь в шаблоны, Вы поразитесь тому, какой мощный это инструмент и какие возможности он предоставляет.
Шаблоны (справочник по C#)
Возможность использовать сопоставление шаблонов впервые появилась в C# 7.0. С тех пор в каждой новой основной версии C# возможности сопоставления шаблонов расширяются. Сопоставление шаблонов поддерживают следующие выражения и операторы C#:
В этих конструкциях можно сравнить входное выражение с любым из следующих шаблонов:
Логические шаблоны, шаблоны свойств и позиционные шаблоны являются рекурсивными шаблонами. То есть, они могут содержать вложенные шаблоны.
Пример использования этих шаблонов для создания управляемого данными алгоритма можно посмотреть в разделе Учебник: использование сопоставления шаблонов для создания управляемых типами и управляемых данными алгоритмов.
Шаблоны объявления и шаблоны типов
Шаблоны объявления и шаблоны типов используются для проверки того, совместим ли с указанным типом тип определенного выражения в среде выполнения. С помощью шаблона объявления можно также объявить новую локальную переменную. Если шаблон объявления соответствует выражению, этой переменной присваивается результат преобразованного выражения, как показано в следующем примере:
Начиная с C# 7.0, шаблон объявления с типом T соответствует выражению в том случае, если результат выражения имеет значение, отличное от NULL, и выполняется любое из следующих условий:
В следующем примере показаны два последних условия:
Начиная с C# 9.0, для этой цели можно использовать шаблон типа, как показано в следующем примере:
Как и шаблон объявления, шаблон типа соответствует выражению, если результат выражения не равен NULL, а его тип в среде выполнения удовлетворяет любому из указанных выше условий.
Дополнительные сведения см. в разделах Шаблон объявления и Шаблон типа в примечаниях к предлагаемой функции.
Шаблон константы
Начиная с C# 7.0, вы можете использовать шаблон константы для проверки того, равен ли результат выражения заданной константе, как показано в следующем примере:
В шаблоне константы можно использовать любое константное выражение, например:
Начиная с C# 9.0, вы можете использовать шаблон константы null с отрицанием для проверки неравенства значению NULL, как показано в следующем примере:
Дополнительные сведения см. в разделе Шаблон константы в примечании к предлагаемой функции.
Реляционные шаблоны
Начиная с C# 9.0, вы можете использовать реляционный шаблон для сравнения результата выражения с константой, как показано в следующем примере:
Чтобы проверить, находится ли результат выражения в определенном диапазоне, сопоставьте его с шаблоном конъюнкции ( and ), как показано в следующем примере:
Если результат выражения — null или его не удается преобразовать в тип константы с помощью преобразования, допускающего значение NULL, или распаковки-преобразования, то реляционный шаблон не соответствует выражению.
Дополнительные сведения см. в разделе Реляционные шаблоны в примечании к предлагаемой функции.
Логические шаблоны
Как показано в предыдущем примере, блоки объединения в шаблоне можно использовать многократно.
Дополнительные сведения см. в разделе Блоки объединения шаблонов в примечании к предлагаемой функции.
Шаблон свойства
Начиная с C# 8.0, вы можете использовать шаблон свойства для сопоставления свойств или полей выражения с вложенными шаблонами, как показано в следующем примере:
Шаблон свойства соответствует выражению, если результат выражения не равен NULL, а каждый вложенный шаблон соответствует соответствующему свойству или полю результата выражения.
Вы также можете добавить проверку типа среды выполнения и объявление переменной в шаблон свойства, как показано в следующем примере:
Шаблон свойства является рекурсивным шаблоном. Это значит, что любой шаблон можно использовать как вложенный шаблон. Используйте шаблон свойства для сопоставления элементов данных с вложенными шаблонами, как показано в следующем примере:
В предыдущем примере используются две возможности, доступные в C# 9.0 и более поздних версиях языка: блок объединения шаблонов or и типы записей.
Начиная с C# 10.0 можно ссылаться на вложенные свойства или поля в шаблоне свойства. Например, можно выполнить рефакторинг метода из предыдущего примера в следующий эквивалентный код:
Дополнительные сведения см. в разделе Шаблон свойства в примечании к предлагаемой функции и примечание к предлагаемой функции Расширенные шаблоны свойств.
Позиционный шаблон
Начиная с C# 8.0, вы можете использовать позиционный шаблон для деконструкции результата выражения и сравнения результирующих значений с соответствующими вложенными шаблонами, как показано в следующем примере:
В предыдущем примере тип выражения содержит метод Deconstruct, используемый для деконструкции результата выражения. Можно также сопоставлять выражения кортежных типов с позиционными шаблонами. Таким образом можно сопоставить несколько входных значений с различными шаблонами, как показано в следующем примере:
В предыдущем примере используются реляционные и логические шаблоны, доступные в C# 9.0 и более поздних версиях языка.
Можно также расширить позиционный шаблон одним из следующих способов:
Добавьте проверку типа среды выполнения и объявление переменной, как показано в следующем примере:
Используйте шаблон свойства в позиционном шаблоне, как показано в следующем примере:
Можно объединить два предыдущих варианта, как показано в следующем примере:
Позиционный шаблон является рекурсивным шаблоном. Это значит, что любой шаблон можно использовать как вложенный шаблон.
Дополнительные сведения см. в разделе Позиционный шаблон в примечании к предлагаемой функции.
Шаблон var
В шаблоне var тип объявленной переменной равен установленному во время компиляции типу выражения, сопоставляемого с данным шаблоном.
Дополнительные сведения см. в разделе Шаблон var в примечании к предлагаемой функции.
Шаблон пустой переменной
В предыдущем примере шаблон пустой переменной используется для обработки значения null и любых целочисленных значений, которые не соответствуют имеющимся членам перечисления DayOfWeek. Благодаря этому гарантируется, что выражение switch в приведенном примере сможет обработать все возможные входные значения. Если в выражении switch не используется шаблон пустой переменной и при этом ни один из шаблонов выражения не соответствует входным данным, среда выполнения генерирует исключение. Если выражение switch не обрабатывает все возможные входные значения, компилятор генерирует предупреждение.
Дополнительные сведения см. в разделе Шаблон пустой переменной в примечании к предлагаемой функции.
Шаблон в круглых скобках
Начиная с C# 9.0, вы можете использовать круглые скобки вокруг любого шаблона. Как правило, это делается для того, чтобы подчеркнуть или изменить приоритет логических шаблонов, как показано в следующем примере:
Спецификация языка C#
Дополнительные сведения см. в следующих примечаниях к предлагаемой функции.
Параметры шаблона
Вы можете заменить значения в шаблоне при создании его экземпляра. Чтобы настроить эту функцию, используйте параметры шаблона. Они позволяют заменить такие значения, как имена классов и пространства имен в шаблоне. Эти параметры заменяет мастер шаблонов, запускающийся в фоновом режиме, когда пользователь добавляет новый элемент или проект.
Объявление и включение параметров шаблона
Включение подстановки параметров в шаблонах
В файле кода для элемента проекта укажите соответствующие параметры. Например, следующий параметр указывает, что безопасное имя проекта используется для пространства имен в файле:
Зарезервированные параметры шаблона
В таблице ниже перечислены параметры зарезервированного шаблона, которые могут использоваться любым шаблоном:
Параметры шаблонов зависят от регистра символов.
Настраиваемые параметры шаблона
Вы можете указать собственные параметры шаблона и значения в дополнение к зарезервированным параметрам шаблона по умолчанию, которые используются во время замены параметров. Дополнительные сведения см. в разделе Элемент CustomParameters (шаблоны Visual Studio).
Пример: использование имени проекта в качестве имени файла
Пример: использование безопасного имени проекта в качестве имени пространства имен
Чтобы использовать безопасное имя проекта для пространства имен в файле класса C#, используйте следующий синтаксис:
В VSTEMPLATE-файл для шаблона проекта включите атрибут ReplaceParameters=»true» при ссылке на файл:
Урок №173. Шаблоны функций
На предыдущих уроках мы рассматривали, как с помощью функций и классов сделать программы удобнее, безопаснее и производительнее.
Шаблоны функций
Хотя функции и классы являются мощными и гибкими инструментами для эффективного программирования, в некоторых случаях они ограничены из-за требования C++ указывать типы всех используемых параметров. Например, предположим, что нам нужно написать функцию для вычисления наибольшего среди двух чисел:
Всё отлично до тех пор, пока мы работаем с целочисленными значениями. А что, если нам придется работать и со значениями типа double? Вы, вероятно, решите перегрузить функцию max() для работы с типом double:
А это, в свою очередь, головная боль для программистов, так как поддерживать такой код непросто как по затраченным усилиям, так и по времени. И самое важное то, что это нарушает одну из концепций эффективного программирования — сократить до минимума дублирование кода. Правда, было бы неплохо написать одну версию функции max(), которая работала бы с параметрами ЛЮБОГО типа?
Это возможно. Добро пожаловать в мир шаблонов!
Если посмотреть определение слова «шаблон» в словаре, то увидим следующее: «Шаблон — это образец, по которому изготавливаются похожие изделия». Например, шаблоном является трафарет — объект (например, пластинка), в котором прорезан рисунок/узор/символ. Если приложить трафарет к другому объекту и распылить краску, то получим этот же рисунок, прилагая минимум усилий, быстро и, что не менее важно, мы сможем сделать десятки этих рисунков разных цветов! При этом нам нужен лишь один трафарет и нам не нужно определять цвет рисунка заранее (до использования трафарета).
В языке C++ шаблоны функций — это функции, которые служат образцом для создания других подобных функций. Главная идея — создание функций без указания точного типа(ов) некоторых или всех переменных. Для этого мы определяем функцию, указывая тип параметра шаблона, который используется вместо любого типа данных. После того, как мы создали функцию с типом параметра шаблона, мы фактически создали «трафарет функции».
При вызове шаблона функции, компилятор использует «трафарет» в качестве образца функции, заменяя тип параметра шаблона на фактический тип переменных, передаваемых в функцию! Таким образом, мы можем создать 50 «оттенков» функции, используя всего лишь один шаблон!
Создание шаблонов функций
Сейчас вам, вероятно, интересно, как создаются шаблоны функций в языке C++. Оказывается, это не так уж и сложно. Рассмотрим еще раз целочисленную версию функции max():
Использование шаблонов в C++
В базовом программировании на C ++ тип данных, например int или char, должен быть указан в объявлении или определении. Такое значение, как 4, 22 или −5, является целым. Такое значение, как «A», «b» или «c», является символом. Механизм шаблонов позволяет программисту использовать универсальный тип для набора фактических типов. Например, программист может решить использовать идентификатор T для int или char. Алгоритм C ++ может иметь более одного универсального типа. С, скажем, T для int или char, U может обозначать тип с плавающей запятой или указатель. Класс, такой как строковый или векторный класс, подобен типу данных, а созданные экземпляры объектов подобны значениям типа данных, который является указанным классом. Таким образом, механизм шаблонов также позволяет программисту использовать идентификатор универсального типа для набора классов.
Шаблон C ++ создает алгоритм, независимый от типа используемых данных. Таким образом, один и тот же алгоритм с множеством экземпляров одного и того же типа может использовать разные типы при разных исполнениях. Сущности переменной, функции, структуры и класса могут иметь шаблоны. В этой статье объясняется, как объявлять шаблоны, как определять шаблоны и как их применять в C ++. Вы должны уже знать вышеупомянутые сущности, чтобы понимать темы, затронутые в этой статье.
Скалярные типы: void, bool, char, int, float и pointer.
Классы как типы
Конкретный класс можно рассматривать как тип, а его объекты — как возможные значения.
Универсальный тип представляет собой набор скалярных типов. Список скалярных типов обширен. Тип int, например, имеет другие связанные типы, такие как short int, long int и т. Д. Универсальный тип также может представлять набор классов.
Переменная
Пример объявления и определения шаблона следующий:
Прежде чем продолжить, обратите внимание, что такого рода операторы не могут появляться в функции main () или в любой области блока. Первая строка — это объявление заголовка шаблона с выбранным программистом универсальным именем типа T. Следующая строка — это определение идентификатора pi, который относится к универсальному типу T. Точность того, является ли T. int, float или какой-либо другой тип может быть выполнен в функции C ++ main () (или какой-либо другой функции). Такая точность будет сделана с переменной pi, а не T.
Первая строка — это объявление заголовка шаблона. Это объявление начинается с зарезервированного слова, шаблона, а затем с открытой и закрытой угловых скобок. В угловых скобках указан как минимум один идентификатор универсального типа, например T, указанный выше. Может быть несколько идентификаторов универсального типа, каждому из которых предшествует зарезервированное слово typename. Такие универсальные типы в этой позиции называются параметрами шаблона.
Следующий оператор может быть записан в main () или в любой другой функции:
И функция отобразит 3.14. Выражение pi определяет точный тип T для переменной pi. Специализация определяет конкретный тип данных для параметра шаблона. Создание экземпляра — это внутренний процесс C ++ по созданию определенного типа, такого как float, в данном случае. Не путайте создание экземпляра параметра шаблона и создание экземпляра класса. В теме шаблона многие типы данных могут иметь одно общее имя типа, тогда как многие классы могут иметь одно общее имя класса. Однако общее имя класса для классов просто называется классом, а не именем класса. Кроме того, значение относится к типу данных, например int, так же как созданный объект относится к классу, например классу String.
При специализации выбранный тип данных, например float, помещается в угловые скобки после переменной. Если в объявлении заголовка шаблона содержится более одного параметра шаблона, в выражении специализации будет соответствующее количество типов данных в том же порядке.
В специализации тип известен как аргумент шаблона. Не путайте это с аргументом функции для вызова функции.
Тип по умолчанию
Если при специализации тип не указан, предполагается тип по умолчанию. Итак, из следующего выражения:
template typename U = const char *>
U pi = «love» ;
«любовь» к постоянному указателю на char. Обратите внимание в объявлении, что U = const char *. Угловые скобки будут пустыми при специализации (тип не указан); фактический тип считается константным указателем на char, тип по умолчанию. Если бы при специализации требовался какой-то другой тип, то имя типа записывалось бы в угловых скобках. Если для специализации требуется тип по умолчанию, повторение типа в угловых скобках необязательно, т. Е. Угловые скобки можно оставить пустыми.
Примечание: тип по умолчанию все еще можно изменить при специализации, установив другой тип.
Структура
В следующем примере показано, как параметр шаблона можно использовать со структурой:
template typename T > struct Ages
<
T John = 11 ;
T Peter = 12 ;
T Mary = 13 ;
T Joy = 14 ;
> ;
Это возраст учащихся класса (класса). Первая строка — это объявление шаблона. Тело в фигурных скобках — это фактическое определение шаблона. Возраст можно вывести в функции main () следующим образом:
Ages int > grade7 ;
cout grade7. John ‘ ‘ grade7. Mary ‘ \n ‘ ;
Результат: 11 13. Первый оператор здесь выполняет специализацию. Обратите внимание, как это было сделано. Он также дает имя для объекта структуры: grade7. Второй оператор имеет обычные выражения объекта структуры. Структура похожа на класс. Здесь Ages похож на имя класса, а grade7 — это объект класса (структура).
Если некоторые значения возраста являются целыми числами, а другие — числами с плавающей запятой, то структуре требуются два общих параметра, как показано ниже:
Соответствующий код для функции main () выглядит следующим образом:
Результат: 11 12.3. При специализации порядок типов (аргументов) должен соответствовать порядку универсальных типов в объявлении.
Объявление шаблона можно отделить от определения следующим образом:
Первый сегмент кода — это просто объявление шаблона (нет присваиваний). Второй сегмент кода, который является просто оператором, является определением идентификатора grade7. Слева — объявление идентификатора grade7. Справа находится список инициализаторов, который присваивает соответствующие значения элементам структуры. Второй сегмент (оператор) можно записать в функцию main (), в то время как первый сегмент остается вне функции main ().
Не тип
Примеры типов, не относящихся к данным, включают int, указатель на объект, указатель на функцию и типы auto. Есть и другие нетипы, которые в этой статье не рассматриваются. Нетип подобен неполному типу, значение которого задается позже и не может быть изменено. В качестве параметра он начинается с определенного не типа, за которым следует идентификатор. Значение идентификатора дается позже, при специализации, и не может быть изменено снова (как константа, значение которой задается позже). Следующая программа иллюстрирует это:
cout grade7. John ‘ ‘ grade7. Joy ‘ \n ‘ ;
При специализации первый тип, int, в угловых скобках используется скорее для формальности, чтобы убедиться, что количество и порядок параметров соответствуют количеству и порядку типов (аргументов). Значение N дано при специализации. Результат: 11 14.6.
Частичная специализация
Предположим, что в шаблоне есть четыре универсальных типа и что среди четырех типов необходимы два типа по умолчанию. Это может быть достигнуто с помощью конструкции частичной специализации, в которой не используется оператор присваивания. Таким образом, конструкция частичной специализации дает значения по умолчанию для подмножества универсальных типов. Однако в схеме частичной специализации необходимы базовый класс (структура) и класс частичной специализации (структура). Следующая программа иллюстрирует это для одного универсального типа из двух универсальных типов:
Определите объявление базового класса и определение его частичного класса. Объявление базового класса в заголовке шаблона имеет все необходимые общие параметры. Объявление заголовка шаблона класса частичной специализации имеет только общий тип. В схеме используется дополнительный набор угловых скобок, который идет сразу после имени класса в определении частичной специализации. Это то, что на самом деле делает частичную специализацию. Он имеет тип по умолчанию и тип, отличный от типа по умолчанию, в порядке, указанном в базовом классе. Обратите внимание, что типу по умолчанию по-прежнему можно присвоить другой тип в функции main ().
Соответствующий код в функции main () может быть следующим:
Пакет параметров шаблона
Пакет параметров — это параметр шаблона, который принимает ноль или более универсальных типов шаблона для соответствующих типов данных. Параметр пакета параметров начинается с зарезервированного слова typename или class. Далее следуют три точки, а затем идентификатор упаковки. Следующая программа показывает, как пакет параметров шаблона может использоваться со структурой:
template typename … Types > struct Ages
<
int John = 11 ;
float Peter = 12.3 ;
int Mary = 13 ;
float Joy = 14.6 ;
> ;
Ages int > gradeB ;
cout gradeB. John ‘ ‘ gradeB. Mary ‘ \n ‘ ;
Ages float > gradeC ;
cout gradeC. Peter ‘ ‘ gradeC. Joy ‘ \n ‘ ;
Ages <> gradeA ; //like default
cout gradeA. John ‘ ‘ gradeA. Joy ‘ \n ‘ ;
11 13
12,3 14,6
11 14,6
11 14,6
Шаблоны функций
Упомянутые выше возможности шаблона применяются аналогично шаблонам функций. В следующей программе показана функция с двумя общими параметрами шаблона и тремя аргументами:
Результат выглядит следующим образом:
В магазине 12 книг стоимостью 500 долларов.
Отделение от прототипа
Определение функции можно отделить от ее прототипа, как показано в следующей программе:
Примечание. Объявление шаблона функции не может появляться в функции main () или в любой другой функции.
Перегрузка
Перегрузка одной и той же функции может происходить с разными объявлениями заголовка шаблона. Следующая программа иллюстрирует это:
В магазине 12 книг стоимостью 500 долларов.
В магазине 12 книг стоимостью 500 долларов.
Шаблоны классов
Упомянутые выше возможности шаблонов применяются аналогично шаблонам классов. Следующая программа представляет собой объявление, определение и использование простого класса:
class TheCla
<
public :
int num ;
static char ch ;
Результат выглядит следующим образом:
В магазине 12 книг стоимостью 500 долларов.
Следующая программа представляет собой указанную выше программу с объявлением заголовка шаблона:
Вместо слова typename в списке параметров шаблона можно использовать слово class. Обратите внимание на специализацию в объявлении объекта. Результат все тот же:
В магазине 12 книг стоимостью 500 долларов.
Разделительная декларация
Объявление шаблона класса можно отделить от кода класса следующим образом:
Работа со статическими членами
В следующей программе показано, как получить доступ к статическому члену данных и статической функции-члену:
using namespace std ;
Присвоение значения статическому элементу данных является объявлением и не может быть в main (). Обратите внимание на использование и расположение универсальных типов и универсального типа данных в операторе присваивания. Кроме того, обратите внимание, что функция-член статических данных была вызвана в main () с фактическими типами данных шаблона. Результат следующий:
Официальная статическая функция-член.
Компиляция
Объявление (заголовок) и определение шаблона должны быть в одном файле. То есть они должны быть в одной единице перевода.
Заключение
Шаблоны C ++ делают алгоритм независимым от типа используемых данных. Сущности переменной, функции, структуры и класса могут иметь шаблоны, которые включают объявление и определение. Создание шаблона также включает в себя специализацию, когда универсальный тип принимает фактический тип. Объявление и определение шаблона должны быть в одной единице перевода.