Я пытаюсь найти лучший способ обойти видимую ошибку, где numeric_limits<T>::max()
возвращает 0, а не максимальное значение.Apple Clang и numeric_limits <unsigned __int128> :: max() равно 0?
Во-первых, программа испытаний:
$ cat test.cxx
#include <iostream>
#include <limits>
int main(int argc, char* argv[])
{
#if (__SIZEOF_INT128__ >= 16)
std::cout << "__int128 is available" << std::endl;
#else
std::cout << "__int128 is not available" << std::endl;
#endif
unsigned __int128 m = std::numeric_limits<unsigned __int128>::max();
if (m == 0)
std::cout << "numeric_limits<unsigned __int128>::max() is 0" << std::endl;
else
std::cout << "numeric_limits<unsigned __int128>::max() is not 0" << std::endl;
return 0;
}
Испытание __SIZEOF_INT128__ >= 16
пришли из обсуждения в списке рассылки GCC на 128-bit integer - nonsensical documentation?.
И результат:
$ c++ -Wall test.cxx -o test.exe
$ ./test.exe
__int128 is available
numeric_limits<unsigned __int128>::max() is 0
компания Apple также отказалась от платформы и инструментов, поэтому сообщение об ошибке не будет проблема исправлена.
Как мы можем решить проблему?
Я не уверен, как действовать. Чтобы исправить проблему в коде, в отличие от приведенного выше минимального примера, нам нужно переопределить функцию в пространстве имен std
действительно. Но overriding a function in std
is not allowed.
Вот пример того, почему его проблема в реальном коде:
template<class T1, class T2>
T1 Add(const T1& t1, const T2& t2)
{
if (std::numeric_limits<T1>::max() - t2 > t1)
throw std::runtime_error("overflow");
return t1 + t2;
}
В коде выше, мы должны обеспечить полную специализацию для каждой комбинации T1 = __int128
и T2
мыслимых. Это нереально.
версия компилятора на проблемном компьютере:
$ c++ --version
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
Однако, прыгая к тестовой машине, не Apple, производит ожидаемые результаты:
$ clang++-3.5 --version
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Thread model: posix
$ clang++-3.5 -Wall test.cxx -o test.exe
$ ./test.exe
__int128 is available
numeric_limits<unsigned __int128>::max() is not 0
Попробуйте новый clang. Я не могу воспроизвести проблему с помощью Apple LLVM версии 8.0.0 (clang-800.0.42.1) '. Я предполагаю, что 'std :: is_arithmetic <__int128> :: value' является' false' в вашей старой версии clang, потому что тогда вы получаете стандартную реализацию ['__libcpp_numeric_limits'] (https://github.com/llvm-mirror/libcxx/blob/master/include/limits), который дает нуль для 'min' /' max'/etc. Кроме того, я думаю, что ваше обнаружение переполнения - UB, если 't2' отрицательный (и тип подписан). – Cornstalks
Вы должны проверить 'is_specialized' перед использованием' numeric_limits' ... –
@Cornstalks - Спасибо. Исправлена версия Apple Clang на OS X 10.9 с Xcode 6.0. Насколько я знаю, других версий нет (и мы не зависим от того, кто их устанавливает или строит их с нуля).Пример «Добавить» предназначен для демонстрации проблемы с полными специализациями, а не с надежным добавлением. – jww