2016-12-09 21 views
5

Mam funkcję:C++ - std :: enable_if dla kilku rodzajów

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

to działa.

Jednak muszę włączyć tę funkcję nie tylko dla int, ale dla float i const char * oraz ... jak to zrobić bez pisania tych samych razy metoda 3x?

Odpowiedz

10

Jak to:

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 
} 
+0

Jedna sugestia. Prawdopodobnie można przypisać 'remove_cv', jeśli kwalifikatory nie mają znaczenia przy wyborze przeciążenia. –

+0

@YanZhou Ponieważ parametr "i" nie jest przekazywany przez odniesienie, ale przez wartość, stałość i niestabilność zostaną usunięte w każdym razie. Dlatego 'T' nie będzie kwalifikował się cv, a' remove_cv' nic nie zrobi dla tego typu. –

2

Ogólny rozwiązanie dla C++ 17 (zaznaczone na 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!!! 
} 
1

Innym generic rozwiązaniem jest użycie std :: dysjunkcję (C++ 17) w celu wykonania logicznych OR. Dopuszczalne typy są określane jako parametry szablonu w wywołaniu funkcji testowej lub można zdefiniować typedef dla specjalizacji.

#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