Класс enable_if
Класс enable_if из заголовочного файла <type_traits>
позволяет условно включать шаблонные функции и классы на этапе
компиляции. В первый параметр мы передаем условие в виде константного
выражения, а во второй - тип, который будет доступен через вложенный
type, если условие истинно. Если условие ложно, то вложенный
type отсутствует, и подстановка шаблона завершается ошибкой
(принцип SFINAE), благодаря чему такая перегрузка просто исключается
из списка кандидатов.
Класс enable_if часто применяют для ограничения перегрузок
шаблонных функций по типу аргумента - например, чтобы одна функция
работала только с целочисленными типами, а другая - только с
указателями. Также существует вспомогательный псевдоним
enable_if_t, который сразу обращается к вложенному type.
Синтаксис
// основной шаблон
template<bool Cond, class T = void>
struct enable_if;
// вспомогательный псевдоним (C++14)
template<bool Cond, class T = void>
using enable_if_t = typename enable_if<Cond, T>::type;
Пример
Давайте напишем две перегрузки функции print: одна будет
принимать только целочисленные типы, а вторая - только типы с
плавающей точкой:
#include <iostream>
#include <type_traits>
using namespace std;
template<class T>
typename enable_if<is_integral<T>::value, void>::type
print(T value)
{
cout << "integral: " << value << endl;
}
template<class T>
typename enable_if<is_floating_point<T>::value, void>::type
print(T value)
{
cout << "floating: " << value << endl;
}
int main()
{
print(12345);
print(3.14);
return 0;
}
Результат выполнения кода:
"integral: 12345"
"floating: 3.14"
Пример
Давайте применим псевдоним enable_if_t, чтобы запись была
короче. Функция twice будет работать только с целочисленными
типами и возвращать удвоенное значение:
#include <iostream>
#include <type_traits>
using namespace std;
template<class T>
enable_if_t<is_integral<T>::value, T>
twice(T value)
{
return value + value;
}
int main()
{
cout << twice(5) << endl;
return 0;
}
Результат выполнения кода:
10
Пример
Давайте используем enable_if в качестве дополнительного
шаблонного параметра функции. Такая функция show будет
доступна только для указателей:
#include <iostream>
#include <type_traits>
using namespace std;
template<class T, typename enable_if<is_pointer<T>::value, int>::type = 0>
void show(T value)
{
cout << "pointer: " << *value << endl;
}
int main()
{
int num = 42;
show(&num);
return 0;
}
Результат выполнения кода:
"pointer: 42"
Смотрите также
-
класс
is_same,
который проверяет совпадение типов -
класс
is_integral,
который проверяет, является ли тип целочисленным -
класс
conditional,
который выбирает тип по условию -
класс
decay,
который убирает ссылки и cv-квалификаторы