Boost logo

Boost Users :

Subject: Re: [Boost-users] [units] (controlled) implicit conversion
From: alfC (alfredo.correa_at_[hidden])
Date: 2010-05-04 11:03:24


Hi Matthias,

On Apr 30, 9:17 am, Matthias Schabel <bo..._at_[hidden]> wrote:
> Perhaps you would be willing to add the atomic system to the Boost distribution?

Seriously, I would love to. What is the best way to share the code and
start the collaboration?

> I expect that there is a reasonable subset of users for whom this would add
> value...

You don't imagine how many. I do quantum chemistry and it is
incredible how your library changed the way I write my codes... With
the certainty that the equations are dimensionally correct and that I
am not messing up with the conversion factors I can concentrate in the
real problem.

> > But for some formulas I would like to allow implicit conversion, for
> > example when adding energies in SI and energies in atomic units (I
> > don't care which direction the conversion is done since I will
> > transform to one of the two at the end of the formula).

> My recollection is that, after much debate, discussion, and contemplation, it was
> decided that allowing implicit conversions created too many problems and
> ambiguities, some of them subtle.

I understand, and I think the debate is not fruitless.

> That being said, it is a common request for functions
> that take arbitrary units of specified dimension. This is relatively straightforward to accomplish
>
> template<class Y,class System>
> void f(const quantity<unit<desired_dimension_type,System>,Y>& arg) {
>         const quantity<desired_unit_to_use_for_internal_calculations,Y>   q(arg);
>         // do something with q
>         return;
>
> }
>
> This doesn't solve your specific request for implicit assignment to work, but is the recommended
> way of doing "implicit" conversion in function arguments. Hope this helps.

Actually by looking at your code and my code I realized that it is
unreasonable to ask for implicit conversion within normal ('=')
assignment. In general assigment is not the cause of the unelegant
code with explicit conversion but are the operations inside of a long
equation what we should focus in. Besides, operator= can't be
overloaded in C++. My example in the original post was misleading
because in concentrated in the assignment rather than in the syntax
improvement I wanted (mainly being able to add quantities in different
systems).

It seems that just by taking care of addition and substraction we have
90% of the problem solved, my approach was the following: overload
binary operator+ and operator- in a special namespace (e.g. called
"si_conversion" --suggestions accepted--). In such a way that the
following code works:

        quantity<si::energy> een1(1.e-17*si::joules);
        quantity<atomic::energy> een2(2.*atomic::hartree);

---> using namespace
boost::units::atomic::si_conversion; //"activates" implicit convertion
on addition in the current scope

        quantity<atomic::energy> een3(een1+een2); // addition works here
because operator+(si_unit, atomic_unit) is in scope

and this is the code for operator+ and operator-, in principle should
work for any physical dimension from atomic system to si system.

namespace boost{
namespace units{
namespace atomic{
namespace si_conversion{

template<class Dimension, class Y>
quantity<unit<Dimension, atomic::system>, Y> operator+(
        quantity<unit<Dimension, atomic::system>, Y> const& e1,
        quantity<unit<Dimension, si::system >, Y> const& e2
){
        return e1+quantity<unit<Dimension, atomic::system>, Y>(e2); // or e1
+ (quantity<atomic::energy, Y>)e2; ???
}
template<class Dimension, class Y>
quantity<unit<Dimension, atomic::system>, Y> operator+(
        quantity<unit<Dimension, si::system >, Y> const& e1,
        quantity<unit<Dimension, atomic::system>, Y> const& e2
){
        return quantity<unit<Dimension, atomic::system>, Y>(e1)+e2;
}
template<class Dimension, class Y>
quantity<unit<Dimension, atomic::system>, Y> operator-(
        quantity<unit<Dimension, atomic::system>, Y> const& e1,
        quantity<unit<Dimension, si::system >, Y> const& e2
){
        return e1-quantity<unit<Dimension, atomic::system>, Y>(e2);
}
template<class Dimension, class Y>
quantity<unit<Dimension, atomic::system>, Y> operator-(
        quantity<unit<Dimension, atomic::system>, Y> const& e1,
        quantity<unit<Dimension, atomic::system>, Y> const& e2
){
        return quantity<unit<Dimension, atomic::system>, Y>(e1)-e2;
}
}}}}

Thank you
Alfredo


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