我可以在uint_fast64_t和unsigned long long之间实现类型等价吗?

时间:2013-09-13 16:43:03

标签: c++ unsigned-long-long-int

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

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

到GMMs内部格式

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

在MSVC2012下,uint_fast64_t的类型为unsigned long 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 Code中的unsigned long long吗?

2 个答案:

答案 0 :(得分: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的-fno-strict-aliasing)。

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

答案 1 :(得分: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);