Ich habe bei der Verwendung von C ++ - Typmerkmalen ein merkwürdiges Verhalten festgestellt und mein Problem auf dieses skurrile kleine Problem eingegrenzt, für das ich eine Menge Erklärungen geben werde, da ich nichts für Fehlinterpretationen offen lassen möchte.
Angenommen, Sie haben ein Programm wie dieses:
#include <iostream>
#include <cstdint>
template <typename T>
bool is_int64() { return false; }
template <>
bool is_int64<int64_t>() { return true; }
int main()
{
std::cout << "int:\t" << is_int64<int>() << std::endl;
std::cout << "int64_t:\t" << is_int64<int64_t>() << std::endl;
std::cout << "long int:\t" << is_int64<long int>() << std::endl;
std::cout << "long long int:\t" << is_int64<long long int>() << std::endl;
return 0;
}
Bei der 32-Bit-Kompilierung mit GCC (und mit 32- und 64-Bit-MSVC) lautet die Ausgabe des Programms:
int: 0
int64_t: 1
long int: 0
long long int: 1
Das aus einer 64-Bit-GCC-Kompilierung resultierende Programm gibt jedoch Folgendes aus:
int: 0
int64_t: 1
long int: 1
long long int: 0
Das ist merkwürdig, da long long int
ist ein signiertes 64-Bit - Integer und ist für alle Absichten und Zwecke, identisch mit dem long int
und int64_t
Typen, so logisch, int64_t
, long int
und long long int
gleichwertige Typen sein würde - die Anordnung erzeugt wird, wenn diese Arten mit identischem wird. Ein Blick zeigt stdint.h
mir warum:
# if __WORDSIZE == 64
typedef long int int64_t;
# else
__extension__
typedef long long int int64_t;
# endif
In einer 64-Bit-Kompilierung int64_t
ist (offensichtlich) long int
kein long long int
.
Die Lösung für diese Situation ist ziemlich einfach:
#if defined(__GNUC__) && (__WORDSIZE == 64)
template <>
bool is_int64<long long int>() { return true; }
#endif
Aber das ist schrecklich hackisch und lässt sich nicht gut skalieren (tatsächliche Substanzfunktionen uint64_t
usw.). Meine Frage ist also: Gibt es eine Möglichkeit, dem Compiler zu sagen, dass a long long int
auch a ist int64_t
, genau wie es long int
ist?
Meine ersten Gedanken sind, dass dies aufgrund der Funktionsweise von C / C ++ - Typdefinitionen nicht möglich ist. Es gibt keine Möglichkeit, die Typäquivalenz der Basisdatentypen für den Compiler anzugeben, da dies die Aufgabe des Compilers ist (und dies viele Dinge beschädigen kann) und typedef
nur in eine Richtung geht.
Ich bin auch nicht allzu besorgt darüber, hier eine Antwort zu bekommen, da dies ein Super-Duper-Randfall ist, von dem ich nicht vermute, dass sich jemals jemand darum kümmern wird, wenn die Beispiele nicht schrecklich erfunden sind (bedeutet das, dass dies ein Community-Wiki sein sollte?) .
Anhängen : Der Grund, warum ich eine teilweise Vorlagenspezialisierung anstelle eines einfacheren Beispiels verwende, wie:
void go(int64_t) { }
int main()
{
long long int x = 2;
go(x);
return 0;
}
ist, dass das Beispiel noch kompiliert wird, da long long int
es implizit in ein konvertierbar ist int64_t
.
Anhängen : Die einzige Antwort geht bisher davon aus, dass ich wissen möchte, ob ein Typ 64-Bit ist. Ich wollte die Leute nicht irreführen, zu denken, dass mir das wichtig ist, und hätte wahrscheinlich mehr Beispiele dafür liefern sollen, wo sich dieses Problem manifestiert.
template <typename T>
struct some_type_trait : boost::false_type { };
template <>
struct some_type_trait<int64_t> : boost::true_type { };
In diesem Beispiel some_type_trait<long int>
wird a sein , wird es boost::true_type
aber some_type_trait<long long int>
nicht sein. Dies ist zwar in C ++ 's Vorstellung von Typen sinnvoll, aber nicht wünschenswert.
Ein anderes Beispiel ist die Verwendung eines Qualifikationsmerkmals wie same_type
(das in C ++ 0x-Konzepten häufig verwendet wird):
template <typename T>
void same_type(T, T) { }
void foo()
{
long int x;
long long int y;
same_type(x, y);
}
Dieses Beispiel kann nicht kompiliert werden, da C ++ (korrekt) erkennt, dass die Typen unterschiedlich sind. g ++ kann nicht mit einem Fehler wie dem folgenden kompiliert werden: kein übereinstimmender Funktionsaufruf same_type(long int&, long long int&)
.
Ich möchte betonen, dass ich verstehe, warum dies geschieht, aber ich suche nach einer Problemumgehung, die mich nicht zwingt, Code überall zu wiederholen.
sizeof
jeden Typ die gleichen Ergebnisse ? Vielleicht behandelt der Compiler die Größelong long int
anders.