1

我有一个大型代码库,其中包含使用 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 的类型定义为 unsigned long long,因此两个表达式“相同”。

我很清楚它们实际上不是同一类型,因为 unsigned long long 可能正好是 64 位长(长)(因为它是实现定义的),而 uint_fast64_t 至少是 64 位长。( --no-haters ;) )

可悲的是,GCC4.7 和 Clang 3.4 将 uint_fast64_t 称为内部类型,因此无法进行任何类型的强制转换。

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

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

我唯一的选择是手动替换 GMMs 代码中的 unsigned long long 吗?

4

2 回答 2

1

以下是一个不是真正便携但有效的解决方案:

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's -fno-strict-aliasing)。

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

于 2013-09-13T17:10:59.303 回答
0

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);
于 2013-09-13T17:07:55.053 回答