Określ liczbę bitów w typie integralnym w czasie kompilacji

UWAGA: Dodałem podobną, ale znacznie uproszczoną wersję problemu na stronieNiejednoznaczne przeciążenie funkcji, takich jak `msg (długi)` z kandydatami `msg (int32_t)` i `msg (int64_t)`. Ta wersja ma tę zaletę, że jest kompletnym przykładem kompilacji w jednym pliku.

Problem

Mam bibliotekę C z funkcjami takimi jak

<code>obj_from_int32(int32_t& i);
obj_from_int64(int64_t& i);
obj_from_uint32(uint32_t& i);
obj_from_uint64(uint64_t& i);
</code>

W tym przypadku typyint32_t itpnie std te - są zdefiniowane w implementacji, w tym przypadku tablica znaków (w poniższym przykładzie pominąłem konwersję - nie zmienia to pytania, które dotyczy mapowania typów intergral do konkretnej funkcji na podstawie liczby bitów w typ całkowy).

Mam drugą klasę interfejsu C ++, która ma konstruktorów

<code>MyClass(int z);
MyClass(long z);
MyClass(long long z);
MyClass(unsigned int z);
MyClass(unsigned long z);
MyClass(unsigned long long z);
</code>

Uwaga, nie mogę zastąpić tego interfejsustd::int32_t typy stylów - gdybym mógł, nie musiałbym zadawać tego pytania;)

Problem polega na tym, jak wywołać poprawneobj_from_ funkcja oparta na liczbie bitów typu integralnego.

Proponowane rozwiązania

Przedstawiam dwa proponowane rozwiązania, ponieważ żadne rozwiązanie zabójcy nie pojawiło się na szczycie listy, a jest kilka, które są zepsute.

Rozwiązanie 1

Dostarczone przezPozdrawiam i hth. - Alf. Komentarze z tego punktu są moje - możesz komentować i / lub edytować.

Zalety - Dość proste (przynajmniej w porównaniu doboost::enable_if) - Nie polega na bibliotece innych firm (o ile kompilator obsługujetr1)

* Wady ** - Jeśli więcej funkcji (jakanotherObj_from_int32 itp.) są potrzebne, wymagany jest znacznie więcej kodu

To rozwiązanie można znaleźć poniżej - spójrz, to fajne!

Rozwiązanie 2

Zalety

KiedyśConvertFromIntegral Funkcje są wykonywane, dodawanie nowych funkcji, które wymagają konwersji, jest banalne - po prostu napisz zestaw przeładowanyint32_t, int64_t i niepodpisane odpowiedniki.

Użycie szablonów tylko w jednym miejscu, nie rozprzestrzeniają się, ponieważ technika jest ponownie wykorzystywana.

Niedogodności

Może być zbyt skomplikowane, używanieboost::enable_if. Nieco złagodzone przez fakt, że pojawia się tylko raz.

Ponieważ jest to mój własny, nie mogę go zaakceptować, ale możesz go podnieść, jeśli uważasz, że jest czysty (i oczywiście niektórzy ludzie to robiąnie myślę, że w ogóle jest schludny, dlatego tak sądzę!

Rozwiązanie obejmuje funkcję konwersji zint, long ilong long doint32_t iint64_t (i podobne dla wersji niepodpisanych). Jest to połączone z innym zestawem funkcji przeładowanychint32_t, int64_t i niepodpisane odpowiedniki. Obie funkcje można połączyć, ale pierwsze funkcje konwersji tworzą poręczny zestaw narzędzi, który można ponownie wykorzystać, a następnie drugi zestaw funkcji jest trywialnie prosty.

<code>// Utility conversion functions (reuse wherever needed)
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int32_t) && boost::is_signed<InputT>::value,
 int32_t>::type ConvertFromIntegral(InputT z) { return static_cast<int32_t>(z); }

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int64_t) && boost::is_signed<InputT>::value, 
int64_t>::type ConvertFromIntegral(InputT z) { return static_cast<int64_t>(z); }

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint32_t) && boost::is_unsigned<InputT>::value, 
uint32_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint32_t>(z); }

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint64_t) && boost::is_unsigned<InputT>::value, 
uint64_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint64_t>(z); }

// Overload set (mock implementation, depends on required return type etc)
void* objFromInt32 (int32_t i)   { obj_from_int32(i); }
void* objFromInt64 (int64_t& i)  { obj_from_int64(i); }
void* objFromUInt32(uint32_t& i) { obj_from_uint32(i); }
void* objFromUInt64(uint64_t& i) { obj_from_uint64(i); }

// Interface Implementation
MyClass(int z) : _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(long long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned int z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned long long z): _val(objFromInt(ConvertFromIntegral(z))) {}
</code>

Uproszczony (pojedyncza możliwość kompilacji.cpp!) wersja rozwiązania jest podana na stronieNiejednoznaczne przeciążenie funkcji, takich jak `msg (długi)` z kandydatami `msg (int32_t)` i `msg (int64_t)`

questionAnswers(5)

yourAnswerToTheQuestion