Разное поведение с enable_if с использованием clang ++ и g ++ - PullRequest
0 голосов
/ 27 июня 2018

Когда я компилирую следующий код:

#include <boost/numeric/interval.hpp>
#include <complex>

int main(){
  std::complex<boost::numeric::interval<double> > my_interval(1,1);
  my_interval *= my_interval;
  return 0;}

с использованием

g++ -std=c++14 main.cpp

или

clang++ -std=c++14 main.cpp   

У меня два разных поведения. g ++ компилируется нормально, тогда как clang ++ не компилируется, потому что вызывает

std::enable_if<std::is_arithmetic<_A1>::value, bool>::type

отключить некоторые необходимые функции. Есть ли легкое исправление? Я что-то не так делаю?

Версия:

  • g ++ (MacPorts gcc5 5.5.0_1) 5.5.0

  • Apple LLVM версии 8.1.0 (clang-802.0.38)

Полная и полная ошибка:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/complex:599:9: error: 
  no matching function for call to 'isnan'
if (isnan(__x) && isnan(__y))
    ^~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/complex:312:27: note: 
  in instantiation of function template specialization
  'std::__1::operator*<boost::numeric::interval<double,
      boost::numeric::interval_lib::policies<boost::numeric::interval_lib::rounded_math<double>,
  boost::numeric::interval_lib::checking_strict<double> > > >' requested
  here
        *this = *this * complex(__c.real(), __c.imag());
                      ^
main.cpp:6:15: note: in instantiation of function template specialization
  'std::__1::complex<boost::numeric::interval<double,
  boost::numeric::interval_lib::policies<boost::numeric::interval_lib::rounded_math<double>,
  boost::numeric::interval_lib::checking_strict<double> > >
  >::operator*=<boost::numeric::interval<double,
      boost::numeric::interval_lib::policies<boost::numeric::interval_lib::rounded_math<double>,
  boost::numeric::interval_lib::checking_strict<double> > > >' requested
  here
  my_interval *= my_interval;
          ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cmath:424:25: note: 
  candidate template ignored: disabled by 'enable_if' [with _A1 =
  boost::numeric::interval<double,
      boost::numeric::interval_lib::policies<boost::numeric::interval_lib::rounded_math<double>,
  boost::numeric::interval_lib::checking_strict<double> > >]
  typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type

1 Ответ

0 голосов
/ 27 июня 2018

Похоже, что код интервала Boost.Numeric зависит от непереносимого поведения - если быть точным, возможность вызывать isnan для неарифметического типа.

Подпрограммы в <cmath> должны работать только с арифметическими типами, которые определены (в широком смысле) как «встроенные в целочисленные типы и типы с плавающей запятой».

libstdc ++ реализует здесь расширения для поддержки других типов, в libc ++ нет.

Внутри бейсбола: соответствующие части стандарта (и другие биты)

  • [cmath.syn] / 2 - описание предоставляемых перегрузок.
  • [basic.fundamental] / 8 - что такое арифметический тип.
  • Это обсуждалось в рамках выпуска LWG 2086

[Позже]: более основной проблемой (которая приводит к тому, что я сказал выше) является использование std::__1::complex<boost::numeric::interval<double...>.

Это также непереносимо: [complex.numbers] / 2 говорит:

Эффект создания экземпляра шаблонного комплекса для любого типа, кроме float, double или long double, не указан.

...