2013-07-13 34 views
5

Tytuł jest trochę niejednoznaczny.Specjalizacja szablonów dla wielu typów

Powiedzmy mam szablon zdefiniowany jako:

template < typename T > 
void foo (int x) ; 
template <> 
void foo<char> (int x) ; 
template <> 
void foo<unsigned char> (int x) ; 
template <> 
void foo<short> (int x) ; 
... 

Wewnętrznie zarówno foo<signed>() i foo<unsigned>() robią dokładnie to samo. Jedynym wymaganiem jest, aby T był typu 8-bitowego.

mogłem zrobić to poprzez stworzenie kolejny szablon wpisać zdefiniować standardowy typ na podstawie rozmiaru.

template < typename T, size_t N = sizeof(T) > struct remap ; 
template < typename T, size_t > struct remap<1> 
{ 
    typedef unsigned char value; 
} 
... 

Uwaga: szablony funkcji nie mogą mieć parametrów domyślnych. To rozwiązanie przenosi problem tylko do innego szablonu, a także wprowadza problem, jeśli ktoś próbował przekazać typ struktury jako parametr.

Jaki jest najbardziej elegancki sposób, aby rozwiązać ten problem bez powtarzania tych deklaracji funkcji?

To nie jest C++ 11 pytanie.

+0

Czy próbowałeś użyć enable_if, aby sprawdzić rozmiar typu? Zakładam, że robisz to samo dla wszystkich wbudowanych typów tego samego rozmiaru? – Borgleader

+0

@Borgleader enable_if oznacza C++ 11 – Twifty

+2

SFINAE i [ 'enable_if'] (http://en.cppreference.com/w/cpp/types/enable_if) mogą być realizowane w C++ 03 również. – dyp

Odpowiedz

4

trzeba swoją cechę remap po prostu map z typów wejść do typów wyjść i mieć swoją funkcję delegata foo<T>(int) interfejsu do foo_implementation<remap<T>::type>(int) realizacja. tj .:

template <typename T> 
struct remap { 
    // Default: Output type is the same as input type. 
    typedef T type; 
}; 

template <> 
struct remap<char> { 
    typedef unsigned char type; 
}; 

template <> 
struct remap<signed char> { 
    typedef unsigned char type; 
}; 

template <typename T> 
void foo_impl(int x); 

template <> 
void foo_impl<unsigned char>(int x) { 
    std::cout << "foo_impl<unsigned char>(" << x << ") called\n"; 
} 

template <typename T> 
void foo(int x) { 
    foo_impl<typename remap<T>::type>(x); 
} 

See it live at ideone.com.

Powiedział, że to może być realistycznie prostsze do zdefiniowania foo_char, foo_int i foo_short i po prostu zadzwoń do prawidłowego jedną z kodu klienckiego. foo<X>() nie jest syntaktycznie różny od foo_X().

7

Jedną z możliwości jest specjalizują się szablonu klasy dla wielu typów na raz:

// from: http://en.cppreference.com/w/cpp/types/enable_if 
    template<bool B, class T = void> 
    struct enable_if {}; 

    template<class T> 
    struct enable_if<true, T> { typedef T type; }; 

template < typename A, typename B > 
struct is_same 
{ 
    static const bool value = false; 
}; 
template < typename A > 
struct is_same<A, A> 
{ 
    static const bool value = true; 
}; 


template < typename T, typename dummy = T > 
struct remap; 

template < typename T > 
struct remap 
< 
    T, 
    typename enable_if< is_same<T, unsigned char>::value 
         || is_same<T, signed char>::value, T >::type 
> 
{ 
    void foo(int); 
}; 


int main() 
{ 
    remap<signed char> s; 
    s.foo(42); 
} 

Inną możliwością jest specjalizują się szablonu klasy dla kategorii typów (cechy typ):

#include <cstddef> 

template < typename T > 
struct is_integer 
{ 
    static const bool value = false; 
}; 
template<> struct is_integer<signed char> { static const bool value = true; }; 
template<> struct is_integer<unsigned char> { static const bool value = true; }; 


template < typename T, typename dummy = T, std::size_t S = sizeof(T) > 
struct remap; 

template < typename T > 
struct remap 
< 
    T 
    , typename enable_if<is_integer<T>::value, T>::type 
    , 1 // assuming your byte has 8 bits 
> 
{ 
    void foo(int); 
}; 


int main() 
{ 
    remap<signed char> s; 
    s.foo(42); 
} 
+0

Po prostu chciałem zauważyć, że istnieje std :: enable_if, więc nie musisz go definiować samodzielnie. Zobacz [tutaj] (http://en.cppreference.com/w/cpp/types/enable_if). – leetNightshade

+1

@leetNightshade 'enable_if' został dodany w C++ 11; pytanie dotyczy C++ 03 (również, dodałem już komentarz do OP za pomocą tego samego linku;) – dyp

Powiązane problemy