boost::decimal::money - comments on Martin's money classes

Hi, I recently had a need to investigate money classes. I searched for such a beast, since I was sure I wasn't the first to have a need for this, but it was only after I had coded up a good chunk of my own implementation that I came across a boost mailing list thread involving Martin <adrianm@...> and Daniel Frey: http://lists.boost.org/MailArchives/boost/msg77625.php Martin gives a link to his decimal classes here: http://web.telia.com/~u84606172/Boost/ In boostdecimal.zip's boost/decimal/money.hpp, I find the following code: ---- snip ------------------------------------------------------- # define BOOST_MONEY_OPERATOR(op, type) \ template <class DecimalT> \ inline money_base<DecimalT> operator##op(money_base<DecimalT> l, type r) { return l op= r; } \ template <class DecimalT> \ inline money_base<DecimalT> operator##op(type l, money_base<DecimalT> r) { return r op= l; } BOOST_MONEY_OPERATOR(+, int) BOOST_MONEY_OPERATOR(-, int) BOOST_MONEY_OPERATOR(*, int) BOOST_MONEY_OPERATOR(/, int) ---- snip ------------------------------------------------------- As far as I can see, the second item in the BOOST_MONEY_OPERATOR macro is incorrect. Consider: money m = 2; 5 - money(2); This would result in: money(2) -= 5; I'm happy to see some interest in money classes on the boost lists. Is this project still being pursued? Thanks, - Chris

As far as I can see, the second item in the BOOST_MONEY_OPERATOR macro is incorrect. Consider:
money m = 2; 5 - money(2);
This would result in:
money(2) -= 5;
You are right of course. The macro was only a quick fix for a VC70 bug. Other compilers should use the operators library where the left subtraction is disabled. I'm in the process of reworking the library. The focus has changed from decimal arithmetic into money and currency. The current library got basic_money and basic_currency classes based on a money_traits class which handles the adaptation for the underlying arithmetic class. template <typename ArithmeticT, typename TraitsT = money_traits<ArithmeticT> > class basic_money; template <typename MoneyT, typename CurrencyT = currency_type> class basic_currency; typedef basic_money<decimalF64> mymoney; mymoney m(5.25, decimals(2), round_to_nearest); const currency_type EUR("EUR"), USD("USD"); typedef basic_currency<basic_money<decimal64> > mycurrency; mycurrency c(1.23, digits(3), EUR), d(1.23, "USD");

On Mon, Jun 20, 2005 at 11:12:22PM +0000, Martin wrote:
The current library got basic_money and basic_currency classes based on a money_traits class which handles the adaptation for the underlying arithmetic class.
Does the traits class handle rounding?
template <typename ArithmeticT, typename TraitsT = money_traits<ArithmeticT> > class basic_money;
In my attempt at a money class, I have one extra template parameter, which represents the number of digits past the decimal point. I figured this is fundamental enough to be included in the type.
template <typename MoneyT, typename CurrencyT = currency_type> class basic_currency;
typedef basic_money<decimalF64> mymoney; mymoney m(5.25, decimals(2), round_to_nearest);
const currency_type EUR("EUR"), USD("USD"); typedef basic_currency<basic_money<decimal64> > mycurrency; mycurrency c(1.23, digits(3), EUR), d(1.23, "USD");
Nice. This seems similar in direction to Daniel Frey's money classes, which has the weight of actual company usage behind it. The only drawback is that the currency units is not part of the currency type, but rather something checked at runtime via exceptions. What is the rationale behind that? From the outside, it looks safer to catch this at compile time, but I suppose usage of these classes is easier if it is a value? I'd like to be convinced your method is the best. Is the latest code available somewhere? Thanks, - Chris

Does the traits class handle rounding? yes, for each object the rounding mode can be specified including one that is called round_global. round_global means that the rounding is determined from a static variable of the traits class or an application wide setting. What rounding modes are available is of course dependent on the arithmetic type. e.g. For the TR decimal class only round_global is available while decnumber supports both object rounding and global rounding with different traits. (The former is not very efficient since it requires each object to carry a decContext structure)
The basic_money class has the following constructors: money m(V); // floating point, global rounding money m(V, round_to_even); // floating point, local rounding money m(V, decimals(2)); // fixed decimals, global rounding money m(V, digits(8)); // fixed digits, global rounding money m(V, decimals(2), round_to_nearest); money m(V, digits(2), round_to_even); V can be int, double, char*, decimal, money
In my attempt at a money class, I have one extra template parameter, which represents the number of digits past the decimal point. I figured this is fundamental enough to be included in the type.
I use different classes were you can lock precision and/or rounding basic_money<decimal64> digits/decimals decided on object creation basic_money_spec<decimal64, digits, 8> all objects will work with 2 digits basic_money_spec<decimal64, decimals, 2> all objects will work with 2 decimals basic_money_round<decimal64, decimals, 5, round_nearest>
Nice. This seems similar in direction to Daniel Frey's money classes, which has the weight of actual company usage behind it.
yes, I have only generelized his solution a bit (e.g. the currency id type is a template parameter).
The only drawback is that the currency units is not part of the currency type, but rather something checked at runtime via exceptions. What is the rationale behind that? From the outside, it looks safer to catch this at compile time, but I suppose usage of these classes is easier if it is a value? I'd like to be convinced your method is the best.
My plan is to have an extra class with template parameter for type safe currencies. Something like typedef basic_money<decimal> tMoney; typedef basic_currency_fixed<tMoney, 1> tUSD; typedef basic_currenct_fixed<tMoney, 2> tEUR; tMoney a(3); tUSD b(4); tEUR c(5); b = c; // compile error b = a; // ok but I haven't tried it yet so I don't know how feasible and useful it is.
Is the latest code available somewhere?
No, It is still just experimental.
participants (2)
-
Chris Frey
-
Martin