|
Boost Users : |
Subject: Re: [Boost-users] [units][interval] adapt boost.interval for boost.units
From: alfC (alfredo.correa_at_[hidden])
Date: 2010-05-24 14:09:26
On May 23, 10:12 pm, alfC <alfredo.cor..._at_[hidden]> 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
}
};
}}}
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net