
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