Ограничения шаблонов

Оператор requires

Последнее обновление: 31.03.2023

Ограничения шаблонов (как функций, так и классов) позволяют ограничить набор возможных типов, которые будут применяться параметрами шаблонов. Добавляя ограничения к параметрам шаблона, решаются следующие задачи:

  • Из заголовка шаблона сразу видно, какие аргументы шаблона разрешены, а какие нет.

  • Шаблон создается только в том случае, если аргументы шаблона удовлетворяют всем ограничениям.

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

Начиная со стандарта С++20 в язык был добавлен оператор requires, который позволяет установить для параметров шаблонов ограничения.

template <параметры> requires ограничения
содержимое шаблона;

Ограничения представляют условные выражения, которые возвращают значение типа bool - если параметр типа удовлетворяет условию, то возвращается true. Каждое ограничение предписывает одно или несколько требований для одного или нескольких параметров шаблона.

Например, мы хотим определить функцию, которая может складывать числа:

#include <iostream>

template <typename T> requires std::is_same<T, int>::value || std::is_same<T, double>::value
T sum(T a, T b){ return a + b;}

int main()
{
    std::cout << sum(3, 4) << std::endl;
    std::cout << sum(12.5, 4.3) << std::endl;
    //std::cout << sum(5l, 7l) << std::endl;
}

Здесь определен шаблон функции sum, который принимает значения типа T и возвращает их сумму также в виде значения типа T. Для параметра T после слова requires установлено ограничение

std::is_same<T, int>::value || std::is_same<T, double>::value

Для определения ограничения применяется встроенная структура std::is_same из стандартной библиотеки C++. Эта структура в свою очередь типизируется двумя типами. Переменная value структуры возвращает true, если оба типа одинаковы. То есть выражение std::is_same<T, int>::value возвратит true, если T - это int. Аналонично устанавливаем еще одно ограничение к типу - std::is_same<T, double>::value. И с помощью операции || объединяем два ограничения. То есть T может представлять либо int, либо double.

Далее мы можем передавать в функцию sum() значения типов, которые удовлетворяют этим ограничениям:

std::cout << sum(3, 4) << std::endl;        // передаем int
std::cout << sum(12.5, 4.3) << std::endl;   // передаем double

Значения других же типов мы передать не можем. Так, в примере выше закомментрирована строка, где в функцию sum() передаются значения типа long:

//std::cout << sum(5l, 7l) << std::endl;  // long работать не будет

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

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850