
Boost : 
From: Eric Ford (azsro001_at_[hidden])
Date: 20030306 14:14:48
> > This promises to meet a massive need,
> > but for me must wait until I get MSVC 7.1
> > which I understand includes partial specialisation.
> I don't see why partial specialization should be required for this
> application.
Actually, I'm not sure if what I'm doing counts. I've never really paid attention
to this.
It is important to allow appropriate arithmetic operations between
quantities with different dimensions. It is also be important to
allow for numeric type promotion. (Although, this is only crudely
implemented (as promote_numeric+type<A,B> for now). I'm hoping
someone else will offer code for this. Fernando C?) It's important
to keep separate dimensioned quantities which are in different unit
systems (e.g., we don't want to add meter (length in SI) and second
(length in relativistic units).
So I use templates which take multiple parameters, and then specialize
them where some of the template parameters are fixed and other
template parameters are not fixed. Sorry if this is bad terminology.
Here's an example of the code...
Each Dimensioned type is a typedef for base_dimen<NumT, SystemT, DimListT>.
NumT is the numeric type used to store the number.
SystemT specifies what dimension system (e.g., standard, relativistic) is being used.
DimListT is a list of fractions which specifies the dimensions of the particular variable in terms of the base dimensions.
When a user multiplies (divides) two dimensioned quantities, they generally get
back another dimensioned quantity. However, if they multiply (divide)
two quantities with the same (inverse) dimensions, then they can get back a pure number.
using ebf::units::mks_double;
length l = 3 * meter, w = 2 * meter;
area a = l * w; // length * length must return an area
pure r = l / w; // length / length can return a pure number (pure's DimListT = 0,0,0,...)
double rr = l / w; // length / length can also return a nondimensioned type (double/double > double)
I acheive this flexibility with the following code in
base_dimen<numeric_type,system_type,diml_type>:
// helper classes to allow returning scalar when possible
template<typename ArgNumericType, typename ArgDimList>
struct div_return_type
{
private:
BOOST_CLASS_REQUIRE(ArgNumericType, ebf, NumericConcept);
BOOST_CLASS_REQUIRE(ArgDimList, ebf::dimensions, DimlistConcept);
typedef typename ebf::promote_numeric_type<numeric_type, ArgNumericType>::type return_numeric_type;
typedef typename div_diml<diml_type,ArgDimList>::diml_type return_diml_type;
public:
typedef base_dimen<return_numeric_type,system_type,return_diml_type> type;
};
// Specialization to allow for returning nondimensioned quantity.
template<typename ArgNumericType>
struct div_return_type<ArgNumericType, diml_type >
{
private:
BOOST_CLASS_REQUIRE(ArgNumericType, ebf, NumericConcept);
typedef typename ebf::promote_numeric_type<numeric_type, ArgNumericType>::type return_numeric_type;
public:
typedef return_numeric_type type;
};
// Mixed dimensions operations (within system)
template<typename ArgNumericType, typename ArgDimList>
const typename div_return_type<ArgNumericType,ArgDimList>::type
operator/(const base_dimen<ArgNumericType, system_type, ArgDimList> rhs) const
{ return typename div_return_type<ArgNumericType,ArgDimList>::type (pure()/rhs.pure()); };
I'm not sure if this specialization above counts as partial template
specialization or not. I'm sure some boosters must know.
I suppose the most relevant thing is for someone to try it with a
compiler that doesn't like them. Paul, did you actually try compiling
my code? If not, may you could give it a try? If so, can you let me
know exactly where your compiler wasn't happy?
Thanks,
Eford
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk