1

When I compile the following code:

#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;}

using

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

or

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

I get two different behaviors. g++ compiles fine whereas clang++ fails to compile because calls to

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

disable certain required functions. Is there an easy fix? Am I doing something wrong?

Versions:

  • g++ (MacPorts gcc5 5.5.0_1) 5.5.0

  • Apple LLVM version 8.1.0 (clang-802.0.38)

Full and complete error:

/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
Michael Burr
  • 199
  • 10
  • What versions of GCC and Clang are you using? And what is the *complete* and *full* error you get from Clang? – Some programmer dude Jun 27 '18 at 12:11
  • @Someprogrammerdude I have included the requested information (although I could likely leave out the middle lines of the full and complete error). – Michael Burr Jun 27 '18 at 12:17
  • Potentially [related](https://stackoverflow.com/questions/34158902/c-template-overload-with-enable-if-different-behaviour-with-g-and-clang) – Michael Burr Jun 27 '18 at 13:42

1 Answers1

2

It looks like the Boost.Numeric Interval code depends on non-portable behavior - to be precise, the ability to call isnanon a non-arithmetic type.

The routines in <cmath> are required to work only with arithmetic types, which are defined as (broadly) as "built in integral and floating point types".

libstdc++ implements extensions here to support other types, libc++ does not.

Inside baseball: relevant portions of the standard (and other bits)

  • [cmath.syn]/2 - description of what overloads are provided.
  • [basic.fundamental]/8 - what is an arithmetic type.
  • This was discussed as part of LWG issue 2086

[Later]: A more basic problem (which leads to what I said above) is the use of std::__1::complex<boost::numeric::interval<double...>.

This is non-portable as well: [complex.numbers]/2 says:

The effect of instantiating the template complex for any type other than float, double, or long double is unspecified.

Marshall Clow
  • 15,972
  • 2
  • 29
  • 45
  • I saw the unspecified behavior with respect to complex types other than the specified types on the reference pages (so I was somewhat surprised it would work with g++ and not clang++ - I figured that it would work with both or neither). – Michael Burr Jun 27 '18 at 14:12
  • It will depend on compiler support, how various bits of the standard libraries are implemented, etc. It's possible that libstdc++ deliberately decided to support `complex` for user-defined types. – Marshall Clow Jun 28 '18 at 14:59