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.
ProblemIch 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.
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 1Zur 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 2Vorteile
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)"