J'ai eu un comportement étrange en utilisant des traits de type C ++ et j'ai réduit mon problème à ce petit problème bizarre pour lequel je vais donner une tonne d'explications car je ne veux rien laisser ouvert à une mauvaise interprétation.
Disons que vous avez un programme comme celui-ci:
#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;
}
Dans les deux compilations 32 bits avec GCC (et avec MSVC 32 et 64 bits), la sortie du programme sera:
int: 0
int64_t: 1
long int: 0
long long int: 1
Cependant, le programme résultant d'une compilation GCC 64 bits affichera:
int: 0
int64_t: 1
long int: 1
long long int: 0
C'est curieux, car il long long int
s'agit d'un entier 64 bits signé et, à toutes fins utiles, identique aux types long int
et int64_t
, donc logiquement int64_t
, long int
et long long int
serait des types équivalents - l'assemblage généré lors de l'utilisation de ces types est identique. Un regard sur stdint.h
me dit pourquoi:
# if __WORDSIZE == 64
typedef long int int64_t;
# else
__extension__
typedef long long int int64_t;
# endif
Dans une compilation 64 bits, int64_t
estlong int
pas un long long int
(évidemment).
La solution à cette situation est assez simple:
#if defined(__GNUC__) && (__WORDSIZE == 64)
template <>
bool is_int64<long long int>() { return true; }
#endif
Mais c'est horriblement hackish et ne s'adapte pas bien (fonctions réelles de la substance uint64_t
, etc.). Ma question est donc la suivante: existe-t-il un moyen de dire au compilateur que a long long int
est aussi a int64_t
, tout commelong int
est?
Mes premières pensées sont que ce n'est pas possible, en raison du fonctionnement des définitions de type C / C ++. Il n'y a pas de moyen de spécifier l'équivalence de type des types de données de base au compilateur, puisque c'est le travail du compilateur (et permettre que cela puisse casser beaucoup de choses) ettypedef
ne va que dans un sens.
Je ne suis pas non plus trop soucieux d'obtenir une réponse ici, car il s'agit d'un cas super-duper edge dont je ne soupçonne pas que quiconque se souciera jamais lorsque les exemples ne sont pas horriblement artificiels (cela signifie-t-il que cela devrait être un wiki de la communauté?) .
Ajouter : La raison pour laquelle j'utilise la spécialisation partielle des modèles au lieu d'un exemple plus simple comme:
void go(int64_t) { }
int main()
{
long long int x = 2;
go(x);
return 0;
}
est que ledit exemple sera toujours compilé, car il long long int
est implicitement convertible en unint64_t
.
Ajouter : La seule réponse à ce jour suppose que je veux savoir si un type est 64 bits. Je ne voulais pas induire les gens en erreur en leur faisant croire que je me soucie de cela et que j'aurais probablement dû fournir plus d'exemples d'où ce problème se manifeste.
template <typename T>
struct some_type_trait : boost::false_type { };
template <>
struct some_type_trait<int64_t> : boost::true_type { };
Dans cet exemple, some_type_trait<long int>
sera un boost::true_type
, maissome_type_trait<long long int>
ne sera pas. Bien que cela ait du sens dans l'idée des types de C ++, ce n'est pas souhaitable.
Un autre exemple consiste à utiliser un qualificatif comme same_type
(qui est assez courant à utiliser dans les concepts C ++ 0x):
template <typename T>
void same_type(T, T) { }
void foo()
{
long int x;
long long int y;
same_type(x, y);
}
Cet exemple ne parvient pas à se compiler, car C ++ voit (correctement) que les types sont différents. g ++ ne parviendra pas à se compiler avec une erreur comme: aucun appel de fonction correspondantsame_type(long int&, long long int&)
.
Je tiens à souligner que je comprends pourquoi cela se produit, mais je recherche une solution de contournement qui ne me force pas à répéter le code partout.
sizeof
chaque type? Peut-être que le compilateur traite la taille delong long int
différemment.