Урок №180. Частичная специализация шаблонов и Указатели

  Юрий Ворон  | 

    | 

  Обновлено 22 Ноя 2018  | 

 394

В уроке о специализации шаблона функции, мы рассматривали шаблон класса Repository:

Мы говорили о проблеме этого шаблона при работе с типом char*, когда выполнялось поверхностное копировании (присваивание указателя) в конструкторе класса Repository. В качестве решения мы использовали полную специализацию шаблона для создания специализированной версии конструктора класса Repository для работы с типом char*, в котором выделялась память и выполнялось глубокое копирование m_value. Вот специализация конструктора и деструктора класса Repository для работы с типом char* (из того же урока):

Хотя всё отлично работает с типом char*, но как насчет других типов указателей (например, int*)? Поскольку T – это любой тип указателя, то при работе с тем же int* выполниться поверхностное копирование (что нам не нужно), либо нам придется дублировать код выше (специализация конструктора и деструктора), но уже вместо char* писать int*. А дублирование кода, как мы уже знаем, не самый лучший вариант!

К счастью, используя частичную специализацию шаблона, мы можем определить специальную версию класса Repository, которая работала бы со всеми типами указателей (при этом мы не указываем конкретные типы указателей):

И пример на практике:

Результат:

6
8

При объявлении объекта myintptr с типом int*, компилятор видит, что мы ранее определили частичную специализацию шаблона класса для работы с типами указателей, и, учитывая, что мы использовали тип int*, компилятор создаст экземпляр частичной специализации шаблона для работы с типом указателя. Конструктор этой специализации выполняет глубокое копирование параметра x. Позже, когда мы изменяем значение x на 10, myintptr.m_value никак не задевается, так как выполнилось глубокое копирование, при котором m_value получил свою собственную копию x.



Если бы этой частичной специализации не существовало бы, то создался бы экземпляр общего шаблона класса, в котором выполнилось бы поверхностное копирование и myintptr.m_value и x указывали бы на один и тот же адрес памяти. В таком случае, при изменении значения переменной x на 10, мы также бы затронули и значение myintptr (оно также стало бы 10).

Стоит отметить, что, поскольку в нашей частичной специализации копируется только одно значение, то при работе со строками C-style копироваться будет только первый символ (так как строка это массив, а указатель на массив указывает только на первый элемент массива — детальнее в уроке №82). Если же нужно скопировать целую строку, то специализация конструктора (и деструктора) для типа char* должна быть полной. В таком случае, полная специализация будет иметь приоритет выше над частичной специализацией. Например, вот программа, в которой используется как частичная специализация для работы с типами указателей, так и полная специализация для работы с типом char*:

Всё работает как часики:

6
8
Anton

Итого, использование частичной специализации шаблона класса для работы с типами указателей особенно полезно, так как позволяет предусмотреть все возможные варианты использования программы на практике.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (5 оценок, среднее: 5,00 из 5)
Загрузка...

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *