|
Boost : |
From: Matthias Schabel (boost_at_[hidden])
Date: 2007-02-19 15:10:26
Hi Steven,
> It can be done using SFINAE. However,
> 1) All the dimension lists need to be
> processed twice.
> 2) Partial ordering doesn't work.
>
> 2 is solved by concepts. 1 is not.
I agree.
> I've been wondering whether that information
> can be encoded in the system. Here are the
> basics for when each fundamental dimension has
> a unique unit.
This is exactly what I concluded is the way to solve
the problems with dimension_tag being a triple...
What we need is
1) a way to make it possible to use the library in
exactly the way it is used in the current version
when the system is homogeneous (each dimension
is represented by the same system)
2) gracefully handles heterogeneous systems,
reducing them to homogeneous when possible
For 1), I think we can define a specific class to
represent a homogeneous system:
template<class S>
struct homogeneous_system<S>
{
... guarantees that S is the same for all dimensions...
};
We can just overload all the unit operations on this class
template<class System,class Dim>
struct multiply_typeof_helper<unit<homogeneous_system<System>,Dim>,
unit<homogeneous_system<System>,Dim> >
to get our current functionality, then have more general specializations
that work on heterogeneous systems or mixtures of homogeneous and
heterogeneous systems:
template<class System,class Dim>
struct multiply_typeof_helper<unit<heterogeneous_system <System>,Dim>,
unit<heterogeneous_system<System>,Dim> >
you suggest
template<class S>
struct heterogeneous_system<S>
{
... guarantees that S is a list of at least 2 different systems
};
> template<class DimensionMap>
> struct heterogeneous_system {};
>
> template<class DimensionMap>
>
> template<class DimensionMap, class Tag>
> struct unit_info<heterogeneous_system<DimensionMap>, Tag> :
> unit_info<typename mpl::at<DimensionMap, Tag>::type, Tag> {
> };
>
> template<class DimensionMap, class Tag, class System>
> struct
> base_unit_converter<Tag,heterogeneous_system<DimensionMap>,System> :
> base_unit_converter<Tag, typename mpl::at<DimensionMap,
> Tag>::type,System> {
> };
> namespace MGS {
>
> typedef heterogeneous_system<
> mpl::map<
> mpl::pair<length_tag, SI::system>,
> mpl::pair<time_tag, SI::system>,
> mpl::pair<mass_tag, CGS::system>
>>
>> system;
>
> typedef unit<system, energy_type> energy;
>
> energy g_m_squared_per_sec_squared;
>
> }
I like this - this looks like a slick solution. What I would do
is have the typedef resolve to homogeneous_system<> in the
case where all the system tags are identical:
struct system_resolver<S>
{
typedef mpl::map<
mpl::pair<length_tag,SI::system>,
mpl::pair<time_tag,SI::system>,
mpl::pair<mass_tag,SI::system> > >::type
gives
homogeneous_system<SI::system>
and
typedef system_resolver<
mpl::map<
mpl::pair<length_tag,SI::system>,
mpl::pair<time_tag,CGS::system>,
mpl::pair<mass_tag,SI::system> > >::type
gives
typedef heterogeneous_system<
mpl::map<
mpl::pair<length_tag,SI::system>,
mpl::pair<mass_tag,SI::system>,
mpl::pair<time_tag,CGS::system> > >::type
where order is unambiguous - sorted first on system,
then on tag. This way, any unit system also resolves
to a single, well-defined type that you can overload on...
void f(quantity< unit<homogeneous_system<S>,length_type> >)
void f(quantity< unit<heterogeneous_system<whatever>,length_type> >)
In addition, this way we should not incur any additional
compile-time overhead for adding this if the library user
doesn't have any heterogeneous units.
I'm going to work on modifying the existing code to work with
a homogeneous_system type...
Maybe we can have it all...
Matthias
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk