Я поддерживаю библиотеку с открытым исходным кодом, которая должна работать на нескольких платформах и предлагает (среди прочего) математические процедуры для нативных типов данных. Мы хотим предлагать 64-битные вычисления везде, где это возможно.
Нашими целевыми платформами являются Linux и OSX на 32-битной и 64-битной версиях, Windows еще не поддерживается, но известно, что большая часть кода работает под Windows, и поэтому мы сохраняем возможность легкого переноса на Windows в недалеком будущем. будущее. Следовательно, что касается http://en.cppreference.com/w/cpp/language/types, нас интересуют ILP32, LLP64 и LP64. Мы также взаимодействуем с gmp (который предлагает конструкторы только для int
и long
, но не для long long
).
Теперь мы столкнулись с проблемами, которые сводились к тому, какие собственные целочисленные типы мы используем по умолчанию для нашего числового типа:
- Если мы используем
int
, мы возвращаемся к 32 битам на 64-битных платформах. - Если мы используем
long
, у нас будет противоречивое поведение между Linux/OSX 64 и Windows 64: Windows не сможет использовать 64-битные вычисления. - Если мы используем
long long
, использование gmp превращается в беспорядок, потому что созданиеmpz_class
изlong long
приводит к неоднозначной перегрузке. Нам пришлось бы заранее привести числа обратно к long (и, таким образом, эффективно использовать только 32 бита в Windows в ряде мест). - Если мы используем
std::int64_t
и подобные, определения типов различаются между платформами, и, таким образом, мы получаем одни и те же проблемы, просто разные для каждой платформы...
Есть ли какая-то лучшая практика для этого? Можно ли вообще избежать этих проблем или они присущи системе типов 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-or-int64-t-for-portable-code. Я получил некоторое представление о том, что именно происходит и почему это так, но не смог найти решение...
std::int64_t
— это 64-битный целочисленный тип в любой соответствующей реализации.std::size_t
не должно иметь никакого отношения к вашим числам, это тип для выражения размера объекта, ничего больше, ничего больше. И последнее, но не менее важное: никогда не используйтеlong
, если есть какая-либо попытка переносимости. Это самый изменчивый тип. Я даже знаю среду, в которойlong
проверяется при типе регистрации, и наличие этого в вашем коде является блоком для регистрации. - person SergeyA   schedule 21.03.2016intN_t
в том, что они не должны существовать. - person NathanOliver   schedule 21.03.2016