【发布时间】:2016-07-08 09:05:13
【问题描述】:
我维护了一个开源库,该库应该可以在多个平台上运行,并提供(以及其他)本机数据类型的数学例程。我们希望尽可能提供 64 位计算。
我们的目标平台是 32 位和 64 位的 Linux 和 OSX,尚不支持 Windows,但已知大部分代码可在 Windows 下运行,因此我们将保持轻松移植到 Windows 的可能性。如此遥远的未来。因此,对于http://en.cppreference.com/w/cpp/language/types,我们对 ILP32、LLP64 和 LP64 感兴趣。
我们还与 gmp 进行交互(它只提供 int 和 long 的构造函数,但不提供 long long。)
我们现在遇到的问题归结为我们使用哪些原生整数类型作为数字类型的默认值:
- 如果我们使用
int,我们会在 64 位平台上回退到 32 位。 - 如果我们使用
long,Linux/OSX 64 与 Windows 64 之间的行为会不一致:Windows 将无法使用 64 位计算。 - 如果我们使用
long long,使用gmp 会变得一团糟,因为从long long创建mpz_class会导致不明确的过载。我们必须事先将数字转换回 long(因此在 Windows 上的许多地方有效地只使用了 32 位。) - 如果我们使用
std::int64_t等,则不同平台的 typedef 不同,因此我们会遇到相同的问题,只是每个平台的问题不同...
是否有某种最佳实践? 是否有可能避免这些问题,或者它们是 C++ 类型系统所固有的?
当然,问题不止于此。需要考虑的其他未解决问题:
- 每个解决方案如何与
std::size_t进行交互?std::size_t有它的用途,但有时它需要与我们计算的数字交互。显然,我们不想一直来回投射。 - 我们如何处理其他号码类型的使用情况?如果我们提供一个函数
f(T)并为T = int,long,long long提供重载,但用户将它与std::int64_t一起使用,我们能否避免不同平台之间的不一致行为? (std::int64_t的定义不同)如果我们还为std::int64_t提供重载,我们将有重复的重载。
PS:我已经阅读了c-long-long-int-vs-long-int-vs-int64-t 和should-i-use-long-long-or-int64-t-for-portable-code。我对到底发生了什么以及为什么会这样,但无法得出解决方案有所了解...
【问题讨论】:
-
不确定问题是什么。
std::int64_t是任何符合实现的 64 位整数类型。std::size_t应该和你的数字没有任何关系,这是一种表达对象大小的类型,仅此而已。最后但并非最不重要的一点是,如果有任何可移植性尝试,切勿使用long。它是最波动最大的类型。我什至知道在签入类型检查long的环境,并且在您的代码中包含它是签入的块。 -
@SergeyA
intN_t系列类型的问题在于它们不必存在。 -
@NathanOliver,OP 提到了 OS X、Linux 和 Windows。它们确实存在于这些平台上使用的主要 C++ 实现中。