我维护着一个开源库,该库应该在多个平台上运行,并提供(以及其他)本机数据类型的数学例程。我们希望尽可能提供 64 位计算。
我们的目标平台是32位和64位的Linux和OSX,Windows尚不受支持,但已知大多数代码都可以在Windows下运行,因此我们可以在不远的将来轻松移植到Windows。因此,至于 http://en.cppreference.com/w/cpp/language/types,我们对ILP32,LLP64和LP64感兴趣。我们还与 gmp 交互(gmp 只提供 int
和 long
的构造函数,但不提供 long long
的构造函数)。
我们现在遇到了问题,这些问题归结为我们使用哪些本机整数类型作为数字类型的默认值:
- 如果我们使用
int
,我们在 32 位平台上回退到 64 位。 - 如果我们使用
long
,我们在 Linux/OSX 64 与 Windows 64 之间有不一致的行为:Windows 将无法采用 64 位计算。 - 如果我们使用
long long
,使用 gmp 会变得一团糟,因为从long long
创建mpz_class
会导致模棱两可的重载。我们必须事先将数字转换为长整型(因此在许多地方有效地在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和应该使用long-long-long-or-int64-t-for-portable-code。我在那里得到了一些了解,到底发生了什么以及为什么会这样,但无法得出解决方案......
根据定义,Windows 上的 gmp 似乎永远不会支持 64 位值。所以我建议在你的代码中使用int64_t
,任何时候你需要先与gmp交互,static_cast
值long
。