2016-03-21 1 views
0

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 de mpz_class à partir d'un long 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 pour T = int,long,long long mais l'utilisateur l'utilise avec std::int64_t, peut-on éviter un comportement incohérent entre différentes plates-formes? (qui ont des définitions différentes de std::int64_t) Si nous fournissons également des surcharges pour std::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 ...

+0

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

+0

@SergeyA Le problème avec la famille de types 'intN_t' est qu'ils n'ont pas besoin d'exister. – NathanOliver

+0

@NathanOliver, OP mentionne OS X, Linux et Windows. Ils existent sur les principales implémentations C++ utilisées sur ces plates-formes. – SergeyA

Répondre

0

Il semble que, par définition, votre gmp sur Windows 64 ne soutiendra jamais les valeurs de bits. Donc, je suggère simplement d'utiliser int64_t dans votre code, et chaque fois que vous avez besoin d'interagir avec gmp d'abord static_cast la valeur à long.