Bestimmen Sie die Anzahl der Bits im Integraltyp zur Kompilierungszeit

HINWEIS: Ich habe eine ähnliche, aber stark vereinfachte Version des Problems unter hinzugefügtMehrdeutige Überladung von Funktionen wie "msg (long)" mit Kandidaten "msg (int32_t)" und "msg (int64_t)". Diese Version bietet den Vorteil eines vollständigen kompilierbaren Beispiels in einer einzigen Datei.

Problem

Ich habe eine C-Bibliothek mit Funktionen wie

<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>

In diesem Fall die Typenint32_t etc sindnicht dasstd Einsen - sie sind implementierungsdefiniert, in diesem Fall ein Array von Zeichen (im folgenden Beispiel habe ich die Konvertierung weggelassen - es ändert nichts an der Frage, welche Intergraltypen basierend auf der Anzahl der Bits in einer bestimmten Funktion zugeordnet werden der integrale Typ).

Ich habe eine zweite C ++ - Schnittstellenklasse, die Konstruktoren wie hat

<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>

Bitte beachten Sie, dass ich diese Schnittstelle nicht durch ersetzen kannstd::int32_t Stiltypen - wenn ich könnte, müsste ich diese Frage nicht stellen;)

Das Problem ist, wie man das richtige anruftobj_from_ Funktion basiert auf der Anzahl der Bits im Integraltyp.

Vorgeschlagene Lösungen

Ich stelle zwei Lösungsvorschläge vor, da keine Killer-Lösung an die Spitze der Liste gelangt ist und einige davon defekt sind.

Lösung 1

Zur Verfügung gestellt vonProst und hth. - Alf. Kommentare von diesem Punkt an sind meine eigenen - zögern Sie nicht zu kommentieren und / oder zu bearbeiten.

Vorteile - Ziemlich einfach (zumindest im Vergleich zuboost::enable_if) - Verlässt sich nicht auf Bibliotheken von Drittanbietern (sofern der Compiler dies unterstützt)tr1)

* Nachteile ** - Wenn mehr Funktionen (wieanotherObj_from_int32 etc) benötigt werden, ist viel mehr Code erforderlich

Diese Lösung finden Sie weiter unten - werfen Sie einen Blick darauf, es ist raffiniert!

Lösung 2

Vorteile

Sobald dieConvertFromIntegral Funktionen sind erledigt, das Hinzufügen neuer Funktionen, die konvertiert werden müssen, ist trivial - schreiben Sie einfach einen überladenen Satz aufint32_t, int64_t und vorzeichenlose Äquivalente.

Verwendet Vorlagen nur an einer Stelle, sie breiten sich nicht aus, da die Technik wiederverwendet wird.

Nachteile

Könnte mit übermäßig kompliziert seinboost::enable_if. Etwas gemildert durch die Tatsache, dass dies nur an einer Stelle auftritt.

Da dies mein eigenes ist, kann ich es nicht akzeptieren, aber du kannst es positiv bewerten, wenn du denkst, dass es ordentlich ist (und einige Leute tun es offensichtlich)nicht denke, es ist überhaupt ordentlich, deshalb habe ich es abgelehnt, denke ich!) Vielen Dank an alle, die Ideen beigesteuert haben!

Die Lösung beinhaltet eine Umrechnungsfunktion vonint, long undlong long zuint32_t undint64_t (und ähnlich für die nicht signierten Versionen). Dies wird mit einem anderen Satz von Funktionen kombiniert, die überladen sindint32_t, int64_t und vorzeichenlose Äquivalente. Die beiden Funktionen könnten kombiniert werden, aber die ersten Konvertierungsfunktionen stellen ein praktisches Dienstprogramm dar, das wiederverwendet werden kann, und dann ist der zweite Satz von Funktionen trivial einfach.

<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>

Eine vereinfachte (single compilable.cpp!) Version der Lösung finden Sie unterMehrdeutige Überladung von Funktionen wie "msg (long)" mit Kandidaten "msg (int32_t)" und "msg (int64_t)"

Antworten auf die Frage(5)

Ihre Antwort auf die Frage