Boost logo

Boost :

From: Daniel Frey (d.frey_at_[hidden])
Date: 2005-01-08 16:57:49


Martin wrote:
> Daniel Frey <d.frey <at> gmx.de> writes:
>
>>I strongly suggest to use a currency, as otherwise you'll likely miss
>>the intended audience's requirements.
>
> I actually had this implemented at start but removed it at one point. I
> implemented it like this:
>
> template <class DecimalT, int CurrencyId = 0>
> class money_base ...

In our applications, we can't predict the currency of a money variable
at compile-time, and the overhead of the currencies is acceptable due to
the very lean implementation (only 4 bytes, single comparison for checks).

>>money*int is OK, money+int is not. And FWIW, I never saw any of my
>>colleagues complain about money+int not compiling. If the compiler
>>happens to catch it, it usually means that it saved them from a having bug!
>
> And I was afraid my interface was to strict. Thanks.

Safety over convenience. I think most people that actually *work* with
such stuff prefer it that way ;)

>>The application can/should then create central typedefs:
>>
>>typedef basic_decimal<long double> decimal;
>>typedef basic_money<decimal::value_type> money;
>
> Not sure I understand. The implementation of decimal arithmetic will be very
> different depending on the type (e.g. double, int, BCD strings) so I don't see
> how it can all fit into a basic_decimal. It is fine as an ABC but does it
> really add anything (except virtual calls).

> Also shouldn't basic_money use the decimal type instead of the decimal type's
> internal representation (i.e. basic_money<decimal>)

The basic_decimal<T>-class is just a generic float point interface. It
defines what can be done, not how it's done. Example: Depending on T,
some classes have member functions where others have free functions.
It's round(x,2) vs. x.round(2). Combine that with different rounding
modes. When you write your application for one of these types directly,
you are tied to it. Later, when you need to switch the float point type,
you have to change a lot of code. basic_decimal is meant to solve this.
It forwards most calls to the implementations for a type T, unifying the
syntax. Actually, I have a decimal_traits<T>-class which is specialized
for all T's that can be used in our applications with basic_decimal and
basic_money. This is also the reason, why I use basic_money<T> instead
of basic_money<basic_decimal<T>>. This is safer *and* easier for the
user, as it's shorter and basic_money<basic_decimal<T>> can be caught by
the compiler. You can't do that otherwise.

While we are at it: It seems to me that your decimal64 is just a
candidate for a T for basic_decimal<T>. Maybe we should separate both
discussions, as my basic_decimal<T> is not meant to be a cool float
point type in itself.

>>That way, you can switch your complete application for different
>>underlying types that are used for the real calculations easily.
>
> You can do the same with my solution but it would look like this:
>
> typedef money_base<decimal64> money;
> or
> typedef money_base<decimalBCD> money;
>
> typedef money::decimal_type decimal;

Only if decimal64 and decimalBCD have the same interface. And you can't
replace it with double or RWDecimal<RWMP3Int>, because their interfaces
differ.

Regards, Daniel


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