Кратко:
std::enable_if— это вспомогательный шаблон, предоставляемый в стандартной библиотеке C++ (в заголовке<type_traits>), позволяющий включать или исключать шаблоны из рассмотрения в зависимости от выполнения логического условия во время компиляции.
std::enable_if принимает два параметра: условие и тип. Если условие истинно (true), то тип определяется как второй параметр (обычно void). Если условие ложно (false), инстанцирование шаблона не происходит.
Ключевые техники
- Использование
std::enable_ifв качестве возвращаемого типа или параметра шаблона: Основной способ примененияenable_if— включение его в сигнатуру функции или шаблона класса. - Проверка типов с
std::is_*: Использование стандартных типовых проверок, таких какstd::is_arithmetic,std::is_integralи других, для формирования условий вenable_if.
Пример кода
Пример 1: Отключение шаблонов с помощью enable_if
#include <iostream>
#include <type_traits>
// Шаблон функции для числовых типов
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, T>::type
add(T a, T b) {
return a + b;
}
// Перегрузка функции для остальных типов
template <typename T>
typename std::enable_if<!std::is_arithmetic<T>::value, T>::type
add(T a, T b) {
return T(); // Возвращает значение по умолчанию
}
int main() {
std::cout << add(3, 4) << std::endl; // 7 (числовые типы)
std::cout << add(std::string("Hello, "), std::string("world!")) << std::endl; // пустая строка (остальные типы)
}Пример 2: Использование enable_if для ограничения специализаций класса
#include <iostream>
#include <type_traits>
// Общий шаблон класса
template <typename T, typename Enable = void>
class MyClass;
// Специализация для числовых типов
template <typename T>
class MyClass<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> {
public:
void print() {
std::cout << "Arithmetic type" << std::endl;
}
};
// Специализация для остальных типов
template <typename T>
class MyClass<T, typename std::enable_if<!std::is_arithmetic<T>::value>::type> {
public:
void print() {
std::cout << "Non-arithmetic type" << std::endl;
}
};
int main() {
MyClass<int> numType;
numType.print(); // Arithmetic type
MyClass<std::string> nonNumType;
nonNumType.print(); // Non-arithmetic type
}