
On May 23, 10:12 pm, alfC <alfredo.cor...@gmail.com> wrote:
boost::numeric::interval<boost::units::quantity<boost::units::si::energy>
iv(3.*boost::units::si::meter, 4.*boost::units::si::meter);
doesn't compile because of an error in boost/numeric/interval/ checking.hpp (error attached below).
answering to myself... I hope this is useful for someone and for the Units and Interval maintainers. Boost Interval has an unfortunate line of code in boost/numeric/ interval/checking.hpp that reads static T empty_lower() { return (std::numeric_limits<T>::has_quiet_NaN ? std::numeric_limits<T>::quiet_NaN() : static_cast<T>(1) // units can not be constructed from plain numbers (int or other) ); } inside the template class 'checking_base'. The trick to make interval work with units is to specialize the class checking_base to change the behaviour of this particular function. Also unfortunate is the fact that the checking_base member functions are defined inside the class so the whole checking_base class has to be rewritten during the specialization, including member functions that remain unchanged. So if you want to declare a units interval as boost::numeric::interval<boost::units::quantity<boost::units::si::energy>
you need to include the code below (see at end). The code seems to be as generic as possible, it should work with any unit. Now I still have two questions: Whether it is possible to add a shorter specialization code that only specializes only empty_lower(). The second question is what is the magic that makes units constructible from integer 0 and not from integer 1 (note that because of this I can keep empty_upper unchanged). Thank you, Alfredo adaptation of Boost.Interval for Boost.Units: namespace boost {namespace numeric {namespace interval_lib { template<class Unit> struct checking_base<boost::units::quantity<Unit> >{ typedef boost::units::quantity<Unit> T; //this is to keep most of the code unchanged static T pos_inf(){ assert(std::numeric_limits<T>::has_infinity); return std::numeric_limits<T>::infinity(); } static T neg_inf(){ assert(std::numeric_limits<T>::has_infinity); return -std::numeric_limits<T>::infinity(); } static T nan(){ assert(std::numeric_limits<T>::has_quiet_NaN); return std::numeric_limits<T>::quiet_NaN(); } static bool is_nan(const T& x){ return std::numeric_limits<T>::has_quiet_NaN && (x != x); } static T empty_lower(){ return (std::numeric_limits<T>::has_quiet_NaN ? std::numeric_limits<T>::quiet_NaN() : T::from_value(1) // <-- basically the only change ); } static T empty_upper(){ return (std::numeric_limits<T>::has_quiet_NaN ? std::numeric_limits<T>::quiet_NaN() : static_cast<T>(0) ); } static bool is_empty(const T& l, const T& u){ return !(l <= u); // safety for partial orders } }; }}}