
Your decimal64 is both an interface *and* an implementation. I just suggest to separate it. Let basic_decimal take care of the interface, while decimal64 takes care of the implementation.
I can agree that the interface could be formally specified as a basic_decimal but still don't understand the benefits of a decimal_traits vs a class that implements the basic_decimal interface. There are several string types which implements the basic_string interface (fixed_string, const_string, flex_string etc) and they all work without string_traits. Since I am familiar with the string type maybe you can explain what the benefits would be if all string types were implemented using string_traits instead. One thing that would be nice is if basic_decimal were an ABC and all decimal types were derived from it. That way a function could work on any decimal type without templates or recompiling. Drawback is that it would introduce a virtual call for each operation but since a decimal type is probably slow anyway I don't think it matters.
Maybe I don't understand the question, but I think it should be obvious that a decimal based float point types has a lot of advantages. It's not free of any rounding issues, but the problems are more intuitive. Most people don't have a problem to accept rounding in general, it's just examples like
double d = 0; for( int i=0; i<100; ++i ) d += .01; if( d == 1 ) { ... }
Floating point is difficult to use and you must be aware of its weaknesess. Decimal floating point solves the addition problem above but as soon as you do a division the problems are the same as with binary floating point. Expressions often involves several operations: x = (a + b /c - d)*e; A test like (x == 1) will probaly fail for both a decimal and binary floating point type.
If you really try to store the values exactly, consider:
decimal64 d = 1; d /= 3; d *= 3; if( d == 1 ) { ... }
will this work for your type? How?
It will not work since decimal64 is a fixed precision decimal type and will only store a fixed number of decimals. The above will only work for a rational type. With exact I mean that if the decimal type got 2 decimals then these are stored exactly. 1/3 becomes exactly 0.33. How do you expect epsilon to work here? Should == return true for 0.32 0.33 0.34 or an even wider range? Sound confusing to me.