Boost logo

Boost :

From: Andy Little (andy_at_[hidden])
Date: 2006-08-28 16:03:20


"Ben Strasser" <strasser.ben_at_[hidden]> wrote in message
news:loom.20060828T152134-716_at_post.gmane.org...
>I uploaded the into the boost vault. It's in the units directory and has the
> name alternative_units.zip

Hi Ben,

    I took a look at the library. I liked the idea of being able to define a
runtime evaluable conversion factor, though in Quan:

http://sourceforge.net/projects/quan/

 I guess we would make that a separate class.

I liked the example in basic.cpp. It compiled and ran OK in gcc4.0 but
unfortunately not in VC7.1. Overall the library needs needs to be fleshed out
much more though IMO.

However I disagree that users like to spend time making their own units. Quan
has a fair number of units supplied(still nowhere near enough though) and when
they are available they are very much more convenient to use. Also I/O is
useful.

I looked at how I would do the basic.cpp example in Quan. Note that the units
output comes
in very handy here and also note the use of the predefined units, which saves a
lot of time and effort creating units.

regards
Andy Little

// Copyright Andrew Little, Ben Strasser 2006
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See QUAN_ROOT/quan_matters/index.html for documentation.

/*
    Example inspired by basic.cpp in alternative units which is:

// Copyright 2006 Ben Strasser.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

*/

#include <quan/out/mass.hpp>
#include <quan/out/length.hpp>
#include <quan/out/time.hpp>
#include <quan/out/energy.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <map>

// map quantities in various units
// to a target quantity via their output unit string
// use that to look up the conversion routine
template <typename TargetQuan>
class quantity_map{

    // abstract base class for converting
    // to target fixed_quantity type
    struct abc_converter{
        virtual TargetQuan convert(double val)const=0;
        ~abc_converter(){}
    };

    // implementation of the unit converter
    template <typename SourceQuan>
    struct converter : abc_converter{
        BOOST_MPL_ASSERT((boost::is_convertible<SourceQuan,TargetQuan>));
        TargetQuan convert(double val)const
        {
            return SourceQuan(val);
        }
    };
public:
    typedef boost::shared_ptr<abc_converter> quantity_ptr;
    std::map<std::string,quantity_ptr> m_map;

    template <typename SourceQuan>
    void add_unit()
    {
        BOOST_MPL_ASSERT((boost::is_convertible<SourceQuan,TargetQuan>));
        m_map [units_str(SourceQuan())]
        = quantity_ptr(new converter<SourceQuan>);
    }

    bool find (std::string const & str)const
    {
        return m_map.find(str) != m_map.end();
    }
};

int main()
{
    // fill the maps with units as required
    quantity_map<quan::mass::kg> mass_map;
    mass_map.add_unit<quan::mass::kg>();
    mass_map.add_unit<quan::mass::lb>();

    quantity_map<quan::time::s> time_map;
    time_map.add_unit<quan::time::s>();
    time_map.add_unit<quan::time::min>();
    time_map.add_unit<quan::time::h>();

    quantity_map<quan::length::m> length_map;
    length_map.add_unit<quan::length::m>();
    length_map.add_unit<quan::length::mi>();
    length_map.add_unit<quan::length::yd>();
    length_map.add_unit<quan::length::km>();

    // calculation input variables
    quan::mass::kg my_mass;
    quan::time::s my_time;
    quan::length::m my_distance;

    // user input variables
    std::string str;
    double val;

    while (1){
        std::cout << "How much do you weigh (specify lb or kg)? : ";
        std::cin >> val >> str;
        if ( ! mass_map.find(str)){
            std::cout << "Unfortunately " << str
            << " units arent supported. Try another unit\n";
            continue;
        } else {
            my_mass = mass_map.m_map[str]->convert(val);
            break;
        }
    }
    while (1){
        std::cout << "How far did you walk (specify m, mi, yd, km)? : ";
        std::cin >> val >> str;
        if ( ! length_map.find(str)){
            std::cout << "Unfortunately " << str
            << " units arent supported. Try another unit\n";
            continue;
        } else {
            my_distance = length_map.m_map[str]->convert(val);
            break;
        }
    }
    while (1){
        std::cout << "How long did you take? (specify min, s, h)? : ";
        std::cin >> val >> str;
        if ( ! time_map.find(str)){
            std::cout << "Unfortunately " << str
            << " units arent supported. Try another unit\n";
            continue;
        } else {
            my_time = time_map.m_map[str]->convert(val);
            break;
        }
    }

    quan::energy::J my_energy = my_mass * quan::pow<2>(my_distance / my_time);
    std::cout << "Your kinetic energy was : " << my_energy << '\n';
}

/*
sample output:
How much do you weigh (specify lb or kg)? : 150 lb
How far did you walk (specify m, mi, yd, km)? : 20 mi
How long did you take? (specify min, s, h)? : 4 h
Your kinetic energy was : 339.93 J

*/


Boost list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk