Namespaces
Variants
Views
Actions

std::enable_if

From cppreference.com
< cpp‎ | types
 
 
 
Type support
Basic types
Fundamental types
Fixed width integer types (C++11)
Numeric limits
C numeric limits interface
Runtime type information
Type traits
Primary type categories
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Type properties
(C++11)
(C++11)
(C++11)
(C++14)
Supported operations
Relationships and property queries
(C++11)
(C++11)
(C++11)
(C++11)
Type modifications
(C++11)(C++11)(C++11)
Type transformations
(C++11)
enable_if
(C++11)
(C++11)
Type trait constants
 
Defined in header <type_traits>
template< bool B, class T = void >
struct enable_if;
(since C++11)

If B is true, std::enable_if has a public member typedef type, equal to T; otherwise, there is no member typedef.

This metafunction is a convenient way to leverage SFINAE to conditionally remove functions from overload resolution based on type traits and to provide separate function overloads and specializations for different type traits. std::enable_if can be used as an additional function argument (not applicable to operator overloads), as a return type (not applicable to constructors and destructors), or as a class template or function template parameter.

Contents

[edit] Member types

Type Definition
type either T or no such member, depending on the value of B

[edit] Helper types

template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;
(since C++14)

[edit] Possible implementation

template<bool B, class T = void>
struct enable_if {};
 
template<class T>
struct enable_if<true, T> { typedef T type; };

[edit] Example

#include <type_traits>
#include <iostream>
 
// foo1 overloads are enabled via the return type
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>
std::enable_if_t<std::is_integral<T>::value, T> //Using helper type
    foo1(T t) 
{
    std::cout << "foo1: int\n";
    return t;
}
 
// foo2 overload is enabled via a parameter
template<class T>
T foo2(T t, typename std::enable_if<std::is_integral<T>::value >::type* = 0) 
{
    return t;
}
 
// foo3 overload is enabled via a template parameter
template<class T ,
         typename std::enable_if<std::is_integral<T>::value>::type* = nullptr >
T foo3(T t) // note, function signature is unmodified
{
    return t;
}
 
// A is enabled via a template parameter
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> {
}; // note: for this use case, static_assert may be more appropriate
 
int main()
{
    foo1(1.2); // OK, calls the first version of foo1()
    foo1(10); // OK, calls the second version of foo1()
 
//  foo2(0.1); // compile-time error
    foo2(7); // OK
 
//  foo3(1.2); // compile-time error
    foo3(34); // OK
 
//  A<int> a1; // compile-time error
    A<double> a1; // OK
}

Output:

foo1: float
foo1: int

[edit] See also