我能否在 uint_fast64_t 和无符号长整型之间实现类型等效性

Can I achieve type equivalency between uint_fast64_t and unsigned long long?

本文关键字:实现 长整型 之间 类型 无符号 uint fast64      更新时间:2023-10-16

我有一个大型代码库,其中包含使用 uint_fast64_t 作为索引类型的矩阵相关代码。要使用 GMM 作为求解器后端,我需要从以下位置转换(投射!)向量:

std::vector<uint_fast64_t, std::allocator<uint_fast64_t>>

到 GMM 内部格式

std::vector<unsigned long long, std::allocator<unsigned long long>>

在 MSVC2012 下,uint_fast64_t 被 typedef'd 为无符号长长,因此两个表达式"相同"。

我很清楚它们实际上不是同一类型,因为无符号长可能正好是 64 位长(长)(因为它是实现定义的),而uint_fast64_t至少是 64 位长。( --不仇恨者 ;) )

可悲的是,GCC4.7和Clang 3.4 uint_fast64_t为内部类型,使得任何类型的铸造都是不可能的。

此外,似乎在某些时候,clang 将uint_fast64_t解释为无符号长 - 使其与无符号长长定义更加不兼容。

你从我的痛苦中看到了哪些方法?

我唯一的选择是手动替换GMM代码中的无符号长长吗?

下面是一个不太可移植但有效的解决方案:

static_assert(sizeof(uint_fast64_t) == sizeof(unsigned long long), "This code relies on equivalence of uint_fast64_t and unsigned long long");
std::vector<uint_fast64_t, std::allocator<uint_fast64_t>> src;
std::vector<unsigned long long, std::allocator<unsigned long long>> &after_cast = 
  *reinterpret_cast<std::vector<unsigned long long, std::allocator<unsigned long long>> *>(&src);

您必须在关闭严格类型别名的情况下编译它(例如 Clang 的 -fno-strict-aliasing )。

它依赖于标准中未定义的行为,但通过传递适当的编译器标志,您实际上可以使编译器提供一致的定义。

static_cast应该可以解决问题,因为它们都是数字类型(前提是您的 fast64 整数使用不超过 64 位)。

unsigned long long convert_to_ull(uint_fast64_t i)
{
    return static_cast<unsigned long long>(i);
}

std::vector<uint_fast64_t> origData;
// fill in origData
std::vector<unsigned long long> data;
data.reserve(origData.size());
std::transform(origData.begin(), origData.end(), data.begin(), convert_to_ull);