2011-10-04 17 views
7

Chcę napisać strukturę szablonu foo tak, aby foo<N>::value_type była najbliższą całkowitą liczbą całkowitą (zaokrąglanie w górę) do N. Na przykład foo<32>::value_type => uint32_t, foo<33>::value_type => uint64_t i foo<72>::value_type => uint64_t.Specjalizacja szablonowa dla zakresu wartości

Aby to zrobić, potrzebuję eleganckiego sposobu dostarczania częściowych specjalizacji foo dla zakresu wartości, np. 1 <= N <= 8, aby powrócić do uint8_t i tak dalej, a więc na czwartym. Czy istnieje sposób na osiągnięcie tego celu bez konieczności specjalizacji wszystkiego od 0 do 64.

+0

Nie będzie bezpośredniej metody (jak powiedział Mark), ale może jakiś sprytny szablon metaprogramming trick. Ładne pytanie, czekanie na odpowiedź. –

Odpowiedz

14
template<size_t N> struct select { typedef uint64_t result; }; 
template<> struct select<0> { typedef uint8_t result; }; 
template<> struct select<1> { typedef uint16_t result; }; 
template<> struct select<2> { typedef uint32_t result; }; 

template<size_t N> 
struct foo 
{ 
    enum{D = (N > 32 ? 3 : (N > 16 ? 2 : (N > 8 ? 1 : 0)))}; 

    typedef typename select<D>::result value_type; 

    value_type value; 
}; 

W można użyć std::conditional:

typedef 
    typename std::conditional<(N > 32), uint64_t, 
    typename std::conditional<(N > 16), uint32_t, 
    typename std::conditional<(N > 8), uint16_t, uint8_t> 
    ::type>::type>::type value_type; 

Możesz zdecydować, który z nich jest mniej czytelny.

+1

Uwielbiam się udowodnić, że nie tak. –

+2

Świetna odpowiedź. Czy nie powinno się wyliczać enum {D = (N> 32? 3: (N> 16? 2: (N> 8? 1: 0)))}; ', choć? Tutaj to działa: http://ideone.com/OgXaz – filipe

+0

Och, wow, zrobiłem to w przeszłości, ale to jest _ludzie_ prostsze niż moja wersja! Chociaż mój miał bool (1), char (2-8), ..., długo (33-64) i nieważny (65+) –

1

Parametry szablonu muszą być konkretne, więc nie sądzę, że istnieje sposób na uniknięcie specjalizacji dla każdej wymaganej wartości.

7

@hansmaad odpowiedź jest miły odpowiedź, ale wolałbym użyć (wiecie co ?!) Boost:

boost::uint_t<N>::least // N: bits 

Najmniejszy, wbudowany, unsigned integralną typu z co najmniej n bitów . Parametr powinien być liczbą dodatnią. Błąd kompilacji jest wynikiem, jeśli parametr jest większy niż liczba bitów w największym typie całkowitym .

+0

Bardzo urocze, tym bardziej, że używam boost w moim projekcie, ale nie obsługuje przypadku foo <72> :: value_type rozstrzygającego na największą dostępną liczbę całkowitą. –

Powiązane problemy