Можно ли достичь эквивалентности типов между uint_fast64_t и unsigned long long?

У меня есть большая кодовая база, которая содержит код, связанный с матрицей, используя uint_fast64_t в качестве типа индекса. Чтобы использовать GMM в качестве решающего бэкэнда мне нужно преобразовать (привести!) векторы из:

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 используется typedef’d для unsigned long long, поэтому оба выражения «одинаковы».

Мне хорошо известно, что на самом деле они НЕ одного и того же типа, так как unsigned long long может иметь длину точно 64 бита (long) (как это определено реализацией), а длина uint_fast64_t составляет не менее 64 бит. (—но-ненавистники;))

К сожалению, GCC4.7 и Clang 3.4 называют uint_fast64_t внутренним типом, что делает невозможным любой тип приведения.

Кроме того, кажется, что в какой-то момент clang интерпретирует uint_fast64_t как unsigned long, что делает его еще более несовместимым с длинным беззнаковым определением.

Какие пути вы видите из моих страданий?

Является ли мой единственный вариант замены беззнакового long long в GMM-коде вручную?

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).

Он основан на поведении, которое не определено в стандарте, но, передав соответствующий флаг (ы) компилятора, вы можете фактически заставить свой компилятор обеспечить непротиворечивое определение.

1

Другие решения

static_cast следует делать свое дело, так как все они числовые типы (при условии, что ваши fast64 int не используют более 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);
0

По вопросам рекламы [email protected]