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
#include
#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 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 > len,
std::ostream& os) {
// This (simple, forwarding) implementation must be fully defined
in a header.
return showBondLength( (quantity)len, os);
}
int main()
{
// These constructors all work; conversions are automatic
quantity len1(0.152 * nanometer);
quantity len2(1.52 * angstrom);
quantity len3(1.52 * angstrom);
quantity 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)(1.52 * angstrom), cout );
showBondLength( (quantity)len2, cout );
showBondLength( (quantity)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;
}
/* =================================== */