Кратко:
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
}