Je maintiens une bibliothèque open source qui est censé fonctionner sur plusieurs plates-formes et des offres (entre autres) des routines mathématiques sur les types de données natifs. Nous voulons offrir des calculs 64 bits autant que possible. Nos plates-formes cibles sont Linux et OSX sur 32 bits et 64 bits, Windows n'est pas encore pris en charge mais la plupart du code est connu pour fonctionner sous Windows et donc nous garderions la possibilité de porter facilement sur Windows dans le non -so-lointain avenir. Par conséquent, comme pour http://en.cppreference.com/w/cpp/language/types, nous sommes intéressés par ILP32, LLP64 et LP64. Nous interagissons aussi avec gmp (qui ne propose que des constructeurs pour int
et long
, mais pas long long
.)types entiers à utiliser dans une bibliothèque C++ portable
Nous avons couru maintenant des problèmes qui résumaient à quels types d'entiers natifs que nous utilisons par défaut pour notre type de numéro:
- Si nous utilisons
int
, nous retombons à 32 bits sur 64 plates-formes de bits. - Si nous utilisons
long
, nous avons un comportement incohérent entre Linux/OSX 64 vs Windows 64: Windows ne parviendra pas à employer 64 calculs de bits. - Si nous utilisons
long long
, l'utilisation de gmp devient un désordre car la création dempz_class
à partir d'unlong long
entraîne une surcharge ambiguë. Nous devions repasser les nombres à l'avance (et n'utiliser ainsi que 32 bits sur Windows dans un certain nombre d'endroits.) - Si nous utilisons
std::int64_t
, les typedefs diffèrent d'une plateforme à l'autre. problèmes, juste différents pour chaque plate-forme ...
Existe-t-il une sorte de meilleure pratique pour cela? Est-il même possible d'éviter ces problèmes ou sont-ils inhérents au système de type C++?
Bien sûr, les problèmes ne se terminent pas ici. Autres questions ouvertes à prendre en considération:
- Comment chacune de ces solutions interagit-elle par exemple avec
std::size_t
?std::size_t
a son but, mais parfois, il doit interagir avec les chiffres que nous calculons. Évidemment, nous ne voulons pas faire des va-et-vient tout le temps. - Comment traitons-nous l'utilisation avec d'autres types de nombres? Si nous offrons une fonction
f(T)
et fournissons des surcharges pourT = int,long,long long
mais l'utilisateur l'utilise avecstd::int64_t
, peut-on éviter un comportement incohérent entre différentes plates-formes? (qui ont des définitions différentes destd::int64_t
) Si nous fournissons également des surcharges pourstd::int64_t
, nous aurons des surcharges en double.
PS: Je l'ai déjà lu c-long-long-int-vs-long-int-vs-int64-t et should-i-use-long-long-or-int64-t-for-portable-code. Je suis un aperçu il y a ce qui se passe exactement et pourquoi il est comme ça, mais n'a pas pu obtenir une solution ...
Vous ne savez pas quelle est la question. 'std :: int64_t' est un type entier de 64 bits dans toute implémentation conforme.'std :: size_t' ne devrait avoir aucune relation avec vos nombres, c'est un type pour exprimer la taille de l'objet, rien de plus, rien d'autre. Et enfin, mais pas des moindres, n'utilisez jamais 'long' s'il y a une tentative de portabilité quoi que ce soit. C'est ** le type le plus fluctuant. Je connais même un environnement où 'long' est vérifié au type checkin, et l'avoir dans votre code est un bloc pour checkin. – SergeyA
@SergeyA Le problème avec la famille de types 'intN_t' est qu'ils n'ont pas besoin d'exister. – NathanOliver
@NathanOliver, OP mentionne OS X, Linux et Windows. Ils existent sur les principales implémentations C++ utilisées sur ces plates-formes. – SergeyA