|
Boost Users : |
Subject: Re: [Boost-users] [Units] implicit conversion of quantities
From: Christopher Bruns (cmbruns_at_[hidden])
Date: 2009-03-05 18:37:17
Steven Watanabe wrote:
> In this particular case, I would suggest writing the function as a template
> and casting. In general you can write a forwarding overload that casts as
> appropriate.
Thanks Steven for the advice. I consulted Matthias Schabel off list
to help figure out how to get this working. In case others have
similar needs, I am attaching my modified test program.
/* =================================== */
#include <boost/units/systems/si.hpp>
#include <boost/units/base_units/metric/angstrom.hpp>
#include <iostream>
namespace boost { namespace units
{
typedef metric::angstrom_base_unit::unit_type angstrom_unit;
BOOST_UNITS_STATIC_CONSTANT(angstrom, angstrom_unit);
typedef scaled_base_unit<
si::meter_base_unit,
scale<10, static_rational<-9> > > nanometer_base_unit;
typedef nanometer_base_unit::unit_type nanometer_unit;
BOOST_UNITS_STATIC_CONSTANT(nanometer, nanometer_unit);
} } // namespace boost::units
using namespace boost::units;
using namespace std;
// First version of showBondLength takes a specific quantity type (nanometers)
std::ostream& showBondLength(quantity<nanometer_unit> len, std::ostream& os) {
// This implementation could be compiled into a library.
os << len << std::endl;
}
// Second version of showBondLength can take any length type, and casts it to
// the specific type. The parameter type is a bit long winded for a public API
// method, but not unreadable.
template<class Y>
std::ostream& showBondLength(quantity<unit<length_dimension, Y> > len,
std::ostream& os) {
// This (simple, forwarding) implementation must be fully defined
in a header.
return showBondLength( (quantity<nanometer_unit>)len, os);
}
int main()
{
// These constructors all work; conversions are automatic
quantity<nanometer_unit> len1(0.152 * nanometer);
quantity<angstrom_unit> len2(1.52 * angstrom);
quantity<nanometer_unit> len3(1.52 * angstrom);
quantity<angstrom_unit> len4(0.152 * nanometer);
// These three calls are OK, nanometer quantity is passed
showBondLength(0.152 * nanometer, cout);
showBondLength(len1, cout);
showBondLength(len3, cout);
// Explicit casts to nanometer are OK for angstrom quantities...
// but yuck
showBondLength( (quantity<nanometer_unit>)(1.52 * angstrom), cout );
showBondLength( (quantity<nanometer_unit>)len2, cout );
showBondLength( (quantity<nanometer_unit>)len4, cout );
// These all (used to) fail to compile before templated version was added.
// Users want implicit conversion here from angstroms to nanometers
showBondLength(1.52 * angstrom, cout);
showBondLength(len1, cout);
showBondLength(len2, cout);
showBondLength(len3, cout);
showBondLength(len4, cout);
// Conversion from meters works too
showBondLength(3.0 * si::meters, std::cout);
// Non-length quantities correctly fail to compile
// showBondLength(3.0 * si::seconds, std::cout);
return 0;
}
/* =================================== */
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