Martin Perry
Martin Perry

Reputation: 9527

C++ - std::enable_if for more types

I have a function:

template <typename T,
  typename std::enable_if <std::is_same<T, int>::value == true>::type* = nullptr>
void test(T i)
{
   //process data
}

It works.

However, I need to enable this function not only for int, but for float and const char * as well... how to do this without writing the same method 3x times?

Upvotes: 7

Views: 4621

Answers (4)

Aaron D. Marasco
Aaron D. Marasco

Reputation: 6758

Since this is one of the first hits on Google searches, I figured I'd chime in four years later...

For C++20, it's even simpler:

template <typename T, 
          typename = std::enable_if_t<std::is_same_v<T,Type1> || std::is_same_v<T, Type2>>

Upvotes: 0

user7272101
user7272101

Reputation: 31

A generic solution for C++17 ( checked on godbolt.org)

#include <type_traits>

template< typename U, typename ... Ts > struct belong_to
{
  // before C++17 value will have to be defined recursively on the head of Ts
  static constexpr bool value = (std::is_same< U, Ts >::value || ... );
  using type = typename std::enable_if< value, U > ::type;
};

// usage example:
template< typename T >
using testable = typename belong_to< T, int, float, const char >::type;

template< typename T > void test ( testable< T > i ) 
{
    // test process
}

int main()
{
   test< int        > ( 3 );
   test< float      > ( 3.0 );
   test< const char > ('c');
   // test< signed char >( 1 ); does not compile!!!
}

Upvotes: 3

Spectral Sequence
Spectral Sequence

Reputation: 132

Another generic solution is to use std::disjunction (C++17) in order to perform the logical ORs. The allowable types are specified as template parameters in the call to your test function, or you can define a typedef for the specialization.

#include <iostream>
#include <type_traits>

template <typename... Ts, typename T, typename std::enable_if<std::disjunction<std::is_same<T, Ts>...>::value>::type* = nullptr>
void test(T i)
{
    std::cout << "test\n";
}

int main()
{
    int i = 4;
    test<int, float, const char*>(i);
    //test<float, const char*>(i); // compile fails since no int

    // or use a typedef for the specialization
    typedef void (*specialized_t)(int);
    constexpr specialized_t test2 = &test<int, float, const char*>;
    test2(i);
}

run the code

Upvotes: 1

Ralph Tandetzky
Ralph Tandetzky

Reputation: 23660

Like this:

template <typename T,
  typename std::enable_if <std::is_same<T, int         >::value ||
                           std::is_same<T, float       >::value ||
                           std::is_same<T, const char *>::value>::type* = nullptr>
void test(T i)
{
   //process data
}

Upvotes: 15

Related Questions