Здравствуйте, CrystaX, Вы писали:
Next iteration:
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
using boost::mpl::vector;
using boost::mpl::int_;
using boost::mpl::at;
using boost::mpl::size;
// mass length time
// | | |
// v v v
typedef vector<int_<1>, int_<0>, int_<0> > mass_tag;
typedef vector<int_<0>, int_<1>, int_<0> > length_tag;
typedef vector<int_<0>, int_<0>, int_<1> > time_tag;
typedef vector<int_<0>, int_<1>, int_<-1> > velocity_tag;
typedef vector<int_<1>, int_<2>, int_<-2> > energy_tag;
template <bool Condition, typename T1, typename T2> struct if_else;
template <typename T1, typename T2> struct if_else<true, T1, T2> {typedef T1 type;};
template <typename T1, typename T2> struct if_else<false, T1, T2> {typedef T2 type;};
template <int Value, unsigned Power>
struct meta_power
{
static int const value = meta_power<Value, Power - 1>::value * Value;
};
template <int Value>
struct meta_power<Value, 0>
{
static int const value = 1;
};
template <typename Fraction, int Power>
struct fraction_power
{
static int const nominator = if_else<Power < 0, meta_power<Fraction::denominator, -Power>,
meta_power<Fraction::nominator, Power> >::type::value;
static int const denominator = if_else<Power < 0, meta_power<Fraction::nominator, -Power>,
meta_power<Fraction::denominator, Power> >::type::value;
};
struct SystemInternational {};
struct SystemSGS {};
template <typename Tag, typename System1, typename System2>
struct unit_traits
{
private:
typedef unit_traits<mass_tag, System1, System2> mass_traits;
typedef unit_traits<length_tag, System1, System2> length_traits;
typedef unit_traits<time_tag, System1, System2> time_traits;
static int const p1 = at<Tag, int_<0> >::type::value;
static int const p2 = at<Tag, int_<1> >::type::value;
static int const p3 = at<Tag, int_<2> >::type::value;
public:
static int const nominator =
fraction_power<mass_traits, p1>::nominator *
fraction_power<length_traits, p2>::nominator *
fraction_power<time_traits, p3>::nominator;
static int const denominator =
fraction_power<mass_traits, p1>::denominator *
fraction_power<length_traits, p2>::denominator *
fraction_power<time_traits, p3>::denominator;
};
template <>
struct unit_traits<mass_tag, SystemInternational, SystemSGS>
{
// kg to g -> 1/1000
static int const nominator = 1;
static int const denominator = 1000;
};
template <>
struct unit_traits<mass_tag, SystemSGS, SystemInternational>
{
// g to kg -> 1000/1
static int const nominator = 1000;
static int const denominator = 1;
};
template <>
struct unit_traits<length_tag, SystemInternational, SystemSGS>
{
// m to sm
static int const nominator = 1;
static int const denominator = 1000;
};
template <>
struct unit_traits<length_tag, SystemSGS, SystemInternational>
{
// sm to m
static int const nominator = 1000;
static int const denominator = 1;
};
template <>
struct unit_traits<time_tag, SystemInternational, SystemSGS>
{
static int const nominator = 1;
static int const denominator = 1;
};
template <>
struct unit_traits<time_tag, SystemSGS, SystemInternational>
{
static int const nominator = 1;
static int const denominator = 1;
};
template <typename T, typename System, typename Tag>
class unit
{
public:
explicit unit(T const &t = T()) :value(t) {}
unit(unit const &u) :value(u.value) {}
template <typename OtherSystem>
unit(unit<T, OtherSystem, Tag> const &u)
:value(static_cast<T>(u) * unit_traits<Tag, System, OtherSystem>::nominator /
unit_traits<Tag, System, OtherSystem>::denominator)
{}
operator T () const {return value;}
operator T & () {return value;}
private:
T value;
};
typedef unit<double, SystemSGS, mass_tag> mass_sgs;
typedef unit<double, SystemInternational, mass_tag> mass_si;
typedef unit<double, SystemSGS, length_tag> lenght_sgs;
typedef unit<double, SystemInternational, length_tag> lenght_si;
typedef unit<double, SystemSGS, time_tag> time_sgs;
typedef unit<double, SystemInternational, time_tag> time_si;
typedef unit<double, SystemSGS, velocity_tag> velocity_sgs;
typedef unit<double, SystemInternational, velocity_tag> velocity_si;
typedef unit<double, SystemSGS, energy_tag> energy_sgs;
typedef unit<double, SystemInternational, energy_tag> energy_si;
int main()
{
// Test
mass_sgs m1(1);
mass_si m2(m1);
std::cout << "Mass in SI: " << m2 << ", in SGS: " << m1 << std::endl;
velocity_sgs v1(10);
velocity_si v2(v1);
std::cout << "Velocity in SI: " << v2 << ", in SGS:" << v1 << std::endl;
energy_si e1(0.0001);
energy_sgs e2(e1);
std::cout << "Energy in SI: " << e1 << ", in SGS: " << e2 << std::endl;
return 0;
}
Здесь уже надо указать только коэффициенты преобразования для основных типов (масса, длина, время). Все остальное будет выведено автоматически.
Что еще можно было бы улучшить? На данный момент есть привязка к количеству основных типов и их местоположению. При изменении базовых тагов придется переписывать generic unit_traits. Можно подумать насчет перебора типов автоматически... В общем, подумаю еще.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>