2013-07-13 4 views
5

Название немного неоднозначное.Шаблон специализации для нескольких типов

Допустим, у меня есть шаблон, определяемый как:

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) ; 
... 

Внутренне как foo<signed>() и foo<unsigned>() делать то же самое. Единственное требование - T быть 8-битным типом.

Я мог бы сделать это, создав другой шаблон для ввода типа стандартного типа по размеру.

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

Примечание. Шаблоны функций не могут иметь параметры по умолчанию. Это решение только переносит проблему на другой шаблон, а также вводит проблему, если кто-то попытался передать тип структуры в качестве параметра.

Что является самым элегантным способом решения этой проблемы без повторения этих объявлений функций?

Это не вопрос C++ 11.

+0

Вы пытались использовать enable_if для проверки размера типа? Я предполагаю, что вы делаете то же самое для всех встроенных типов одинакового размера? – Borgleader

+0

@Borgleader enable_if is C++ 11 – Twifty

+2

SFINAE и ['enable_if'] (http://en.cppreference.com/w/cpp/types/enable_if) могут быть реализованы также на C++ 03. – dyp

ответ

4

Вам нужна ваша черта remap, чтобы просто сопоставить типы ввода с типами вывода и передать делегату функции foo<T>(int) значение foo_implementation<remap<T>::type>(int) реализация. то есть:

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.

Сказанное может быть реалистично проще определить foo_char, foo_int и foo_short и просто вызвать правильный код клиента. foo<X>() не синтаксически сильно отличается от foo_X().

7

Одной из возможностей является специализировать шаблон класса для нескольких типов сразу:

// 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); 
} 

Другая возможность состоит в том, чтобы специализировать шаблон класса для категорий типов (свойств типов):

#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

Я просто хотел отметить, что есть std :: enable_if, поэтому вам не нужно определять его самостоятельно. См. [Здесь] (http://en.cppreference.com/w/cpp/types/enable_if). – leetNightshade

+1

@leetNightshade 'enable_if' добавлен в C++ 11; вопрос задает C++ 03 (также, я уже добавил комментарий к OP с той же ссылкой;) – dyp

Смежные вопросы