2016-08-09 16 views
14

W tym przykładzie coord_squared_t jest alias typu całkowitą z co najmniej dwukrotnie większa od rodzaju całkowitej coord_t:C++ Typ całkowitą dwukrotność szerokości danego typu

typedef int_least32_t coord_t; 

coord_squared_t CalculateSquaredHypothenuse(coord_t x, coord_t y){ 
    coord_squared_t _x=x; 
    coord_squared_t _y=y; 
    return _x*_x+_y*_y; 
} 

Co mogą być stosowane do ekspresji coord_squared_t pod względem coord_t? Czy jest coś w standardowej bibliotece, która pozwala mi zrobić coś w rodzaju double_width<coord_t>::type, aby uzyskać prawidłową szerokość, zamiast jawnie wybierać typ?

C++ 11 lub C++ 14 są w porządku.

+6

Dlaczego nie używać naprawionych typów takich jak 'int32_t' i' int64_t'? – NathanOliver

+2

Możesz jawnie odwzorować stałe liczby całkowite ... nic nadzwyczajnego, przyznaję – davidhigh

+0

Mogłem, ale zgodnie z odniesieniem 'int8_t',' int16_t' i przyjaciele są opcjonalne, tylko 'int_leastN_t' jest gwarantowane. Zapisywanie warunków dla czterech typów liczb całkowitych jest rozwiązaniem, ale miałem nadzieję na coś lepszego. – Bernard

Odpowiedz

24

Można użyć boost::int_t:

using coord_squared_t = boost::int_t<sizeof(coord_t)*CHAR_BIT*2>::least; 
+0

Wygląda na to, co chcę, ale to jest bodziec ... Zaznaczę to jako zaakceptowane, jeśli nie ma innych odpowiedzi. – Bernard

+5

@Bernard Co jest nie tak z boostem? Jest to nawet część nagłówkowa. – lisyarus

+0

Nic naprawdę nie tak z doładowaniem; Nie napisałem wystarczająco dużo C++, aby użyć boostu. Myślę, że użyję tego w moim kodzie. – Bernard

10

Jeśli nie chcesz używać Boost może po prostu zaimplementować to ręcznie z niektórych specjalności:

template <class > struct next_size; 
template <class T> using next_size_t = typename next_size<T>::type; 
template <class T> struct tag { using type = T; }; 

template <> struct next_size<int_least8_t> : tag<int_least16_t> { }; 
template <> struct next_size<int_least16_t> : tag<int_least32_t> { }; 
template <> struct next_size<int_least32_t> : tag<int_least64_t> { }; 
template <> struct next_size<int_least64_t> : tag<???> { }; 

// + others if you want the other int types 

, a następnie:

using coord_squared_t = next_size_t<coord_t>; 

Alternatywnie można specjalizować w oparciu o liczbę bitów:

template <size_t N> struct by_size : by_size<N+1> { }; 
template <size_t N> using by_size_t = typename by_size<N>::type; 
template <class T> struct tag { using type = T; }; 

template <> struct by_size<8> : tag<int_least8_t> { }; 
template <> struct by_size<16> : tag<int_least16_t> { }; 
template <> struct by_size<32> : tag<int_least32_t> { }; 
template <> struct by_size<64> : tag<int_least64_t> { }; 

ten sposób coś by_size<45>::type jest int_least64_t powodu dziedziczenia. A następnie staje się tak jak odpowiedź Boost:

using coord_squared_t = by_size_t<2 * CHAR_BIT * sizeof(coord_t)>; 
+1

To prawdopodobnie zadziała wszędzie tam, gdzie pytający naprawdę się tym interesuje, ale wyraża obawy, że "intN_t" są opcjonalne. Zatem opcjonalne jest również to, czy 'int_least64_t' jest co najmniej dwa razy większe od' int_least32_t'. Oba mogą być tego samego typu, nawet (powiedzmy, oba 64 bity), w którym to przypadku 'next_size_t ' jest * nie * podwójną szerokością 'int_least32_t'. Ofc jest wciąż wystarczająco duży, aby pomieścić wynik pomnożenia dwóch wartości, które nie przekraczają 2^31 w skali, więc jeśli kontrolujesz to, co wstawisz do 'coord_t', wtedy wszystko jest w porządku. –

+0

@SteveJessop Wymóg nie jest taki, że "sizeof (next_size_t ) == 2 * sizeof (X)'.Warunkiem jest, aby 'next_size_t ' był w stanie pomieścić następną większą ilość bitów. – Barry

+1

Problem polega na tym, że szablon nie może stwierdzić, czy typ 16-bitowy rzeczywiście był, ponieważ wywołujący używa 16 bitów, lub jeśli był to najmniejszy * rozmiar dostępny, gdy potrzebował tylko 8. Rozmiar domeny, którą planuje użycie może być mniejsze niż rzeczywisty typ, ale na tym powinna opierać się decyzja. –

Powiązane problemy