std::enable_if
Материал из cppreference.com
| Определён в заголовочном файле <type_traits>
|
||
| template< bool B, class T = void > struct enable_if; |
(начиная с C++11) | |
Если B является true, std::enable_if имеет открытый член–typedef type, равный T, в противном случае type не определён.
Эта метафункция используется для условного удаления функций и классов, основываясь на статических свойств типов (type traits), и для предоставления разных перегруженных функций в зависимости от типов. std::enable_if может быть использована:
- в качестве дополнительного аргумента функции (не применимо к перегруженным операторам),
- в качестве возвращаемого типа (не применимо к конструкторам и деструкторам),
- как параметр шаблона класса или функции.
Содержание |
[править] Типы-члены
| Тип | Определение |
type
|
T или нет такого члена, в зависимости от значения B
|
[править] Возможная реализация
template<bool B, class T = void> struct enable_if {}; template<class T> struct enable_if<true, T> { typedef T type; }; |
[править] Примечание
Частая ошибка заключается в определении двух шаблонов функций, которые отличаются только значениями по умолчанию для их аргументов. Это неправильно, так как значения по умолчанию аргументов шаблона не являются частью сигнатуры шаблона, а объявление двух разных шаблонов функций с одной сигнатурой является ошибкой.
struct T { enum { int_t,float_t } m_type; template <typename Integer, typename = std::enable_if_t<std::is_integral<Integer>::value> > T(Integer) : m_type(int_t) {} template <typename Floating, typename = std::enable_if_t<std::is_floating_point<Floating>::value> > T(Floating) : m_type(float_t) {} // Ошибка: нельзя перегрузить };
[править] Пример
Запустить этот код
#include <type_traits> #include <iostream> // Включение перегруженных вариантов foo1 при помощи возвращаемого типа template<class T> typename std::enable_if<std::is_floating_point<T>::value, T>::type foo1(T t) { std::cout << "foo1: float\n"; return t; } template<class T> typename std::enable_if<std::is_integral<T>::value, T>::type foo1(T t) { std::cout << "foo1: int\n"; return t; } // Включение перегруженных вариантов foo2 при помощи дополнительного неиспользуемого параметра template<class T> T foo2(T t, typename std::enable_if<std::is_integral<T>::value >::type* = 0) { return t; } // Включение перегруженных вариантов foo3 при помощи дополнительного параметра шаблона template<class T , class = typename std::enable_if<std::is_integral<T>::value>::type > T foo3(T t) // обратите внимание, сигнатура функции не меняется { return t; } // Включение объявления класса A при помощи дополнительного шаблонного параметра template<class T, class Enable = void> class A; // еще неопределенный (undefined) класс template<class T> class A<T, typename std::enable_if<std::is_floating_point<T>::value >::type> { }; int main() { foo1(1.2); // OK, будет вызвана первая версия foo1() foo1(10); // OK, будет вызвана вторая версия foo1() // foo2(0.1); // ошибка времени компиляции foo2(7); // OK // A<int> a1; // ошибка времени компиляции A<double> a1; // OK }
Вывод:
foo1: float foo1: int
[править] См. также
| (C++17) |
void псевдоним шаблонной переменной (псевдоним шаблона) |

