2017-01-15 11 views
2

Я пытаюсь найти лучший способ обойти видимую ошибку, где 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 
+1

Попробуйте новый 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

+1

Вы должны проверить 'is_specialized' перед использованием' numeric_limits' ... –

+0

@Cornstalks - Спасибо. Исправлена ​​версия Apple Clang на OS X 10.9 с Xcode 6.0. Насколько я знаю, других версий нет (и мы не зависим от того, кто их устанавливает или строит их с нуля).Пример «Добавить» предназначен для демонстрации проблемы с полными специализациями, а не с надежным добавлением. – jww

ответ

1

Написать notstd::numeric_limits<T>:std::numeric_limits<T>

Специализируйте, если для T, у которых есть ошибка, перегрузка static max() (и все остальное) с правильным поведением.

Использовать notstd::numeric_limits в Add.

Или используйте новый компилятор и/или стандартную библиотеку.

+0

Спасибо Як. Мы продвигались к аналогичному решению. Позвольте мне проверить его и отчитаться. – jww