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++17)
(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>
#include <string>
 
namespace detail { struct inplace_t{}; }
void* operator new(std::size_t, void* p, detail::inplace_t) {
    return p;
}
 
// #1, enabled via the return type
template<class T,class... Args>
typename std::enable_if<std::is_trivially_constructible<T,Args&&...>::value>::type 
    construct(T* t,Args&&... args) 
{
    std::cout << "constructing trivially constructible T\n";
}
 
// #2
template<class T, class... Args>
std::enable_if_t<!std::is_trivially_constructible<T,Args&&...>::value> //Using helper type
    construct(T* t,Args&&... args) 
{
    std::cout << "constructing non-trivially constructible T\n";
    new(t, detail::inplace_t{}) T(args...);
}
 
// #3, enabled via a parameter
template<class T>
void destroy(T* t, 
             typename std::enable_if<std::is_trivially_destructible<T>::value>::type* = 0) 
{
    std::cout << "destroying trivially destructible T\n";
}
 
// #4, enabled via a template parameter
template<class T,
         typename std::enable_if<
             !std::is_trivially_destructible<T>{} &&
             (std::is_class<T>{} || std::is_union<T>{})
            >::type* = nullptr>
void destroy(T* t)
{
    std::cout << "destroying non-trivially destructible T\n";
    t->~T();
}
 
// #5, enabled via a template parameter
template<class T,
	typename = std::enable_if_t<std::is_array<T>::value> >
void destroy(T* t) // note, function signature is unmodified
{
    for(std::size_t i = 0; i < std::extent<T>::value; ++i) {
        destroy((*t)[i]);
    }
}
/*
template<class T,
	typename = std::enable_if_t<std::is_void<T>::value> >
void destroy(T* t){} // error: has the same signature with #5
*/
 
// the partial specialization of A is enabled via a template parameter
template<class T, class Enable = void>
class A {}; // primary template
 
template<class T>
class A<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
}; // specialization for floating point types
 
int main()
{
    std::aligned_union_t<0,int,std::string> u;
 
    construct(reinterpret_cast<int*>(&u));
    destroy(reinterpret_cast<int*>(&u));
 
    construct(reinterpret_cast<std::string*>(&u),"Hello");
    destroy(reinterpret_cast<std::string*>(&u));
 
    A<int> a1; // OK, matches the primary template
    A<double> a2; // OK, matches the partial specialization
}

Output:

constructing trivially constructible T
constructing non-trivially constructible T
destroying trivially destructible T
destroying non-trivially destructible T

[edit] See also

(C++17)
void variadic alias template
(alias template) [edit]