
After the builds finally chugged through the build server, I see that std::numeric_limits<Number>::min() and std::numeric_limits<Number>::max() are not constant expressions with clang++ unless c++11 is enabled, so my second idea won’t quite work. From: Chris Cooper <chris.cooper@veranmedical.com<mailto:chris.cooper@veranmedical.com>> Date: Wednesday, April 23, 2014 at 12:20 PM To: "boost@lists.boost.org<mailto:boost@lists.boost.org>" <boost@lists.boost.org<mailto:boost@lists.boost.org>> Subject: Re: Regression test relying on undefined compiler behavior (c++11) Actually, I came up with a better idea: #ifndef BOOST_NO_LIMITS template <class Number> struct complement_traits { BOOST_STATIC_CONSTANT(Number, min = std::numeric_limits<Number>::min()); BOOST_STATIC_CONSTANT(Number, max = std::numeric_limits<Number>::max()); }; #else [SNIP] All the other template stuff for calculating complement_traits for various types #endif From: Chris Cooper <chris.cooper@veranmedical.com<mailto:chris.cooper@veranmedical.com>> Date: Wednesday, April 23, 2014 at 11:59 AM To: "boost@lists.boost.org<mailto:boost@lists.boost.org>" <boost@lists.boost.org<mailto:boost@lists.boost.org>> Subject: Regression test relying on undefined compiler behavior (c++11) libs/utility/numeric_traits_test.cpp generates values complement_traits<Number>::min using a clever recursive template, but that template relies on left-shifting a negative value, and according to the C++11 standard that’s a no-no (“the behavior is undefined”) which means it’s not a constant expression, which means it can’t be calculated at compile time, which means the BOOST_STATIC_ASSERT in line 332 won’t compile, saying “static_assert expression is not an integral constant expression” (I’m using clang++). See discussion here: http://stackoverflow.com/questions/23250651/strange-behavior-with-c-recursiv... In addition, it looks like the existing code also relies on the compiler filling the vacated bits with one’s, which I don’t think is what actually happens. The solution I’ve come up with, is to do the shifting using unsigned values, thus avoiding the compiler no-no, and then putting the result back in the specified type. In other words, replacing line 73 BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT)); With BOOST_STATIC_CONSTANT(Number, min = boost::detail::is_signed<Number>::value ? (Number)(((unsignedlong)(prev::min) << 8) | 0x00FF) : Number(Number(prev::min) << CHAR_BIT) ); I’m using constants ‘8’ and ‘0x00FF’ rather than CHAR_BIT since the code would get really ugly if CHAR_BIT != 8. Thoughts? Thanks, Chris