
My preferred solution is to let the user decide. The return type of any expression has a bitwidth that completely allows for any values of the operands: N + N -> N+1 N * N -> 2N The user can then assign it or cast it if necessary (for example, to minimize intermediate precision). Ok, but does this mean that precisions larger than some fixed bound (32-bit or 64-bit) must be provided? No. All that is needed is a compile-time error when instantiating a type with bit-width larger than 32 or 64. With a little bit of hackery, one can even return a proxy type that allows casting/assigning to an acceptable bit-width but provides a compile error for all other uses.
My worry is that a N32 * N32 operation giving an out of bits compile error would be really annoying in many scenarios (assuming 64 bit is not allowed or considered a performance killer). Perhaps the best would be to make the return type as a trait, but we would still need a convenient default behavior. I think it is important to understand all common usage scenarios and how likely they are to judge if some behavior has least surprise. I have used a fixed point template in a couple of scenarios. The most simple is just as a convenient conversion of external data. For example sound stream input in 32:28 signed fixed point, DSP filter in floats and output in 16:16 signed fixed point. In that scenario I didn't use any arithmetic, so the fixed template was mostly for a convenient easy maintainable notation. In another scenario I replaced a rather complicated float based image processing algorithm with a fixed point to gain speed. In that scenario arithmetic and comparison was used. Some error margin was acceptable so the most important issue was seamless type replacement without having to add casts and conversions to the existing code base. In yet another scenario I used fixed points in high performance computer graphics, where a fixed point type was not relevant since I used MMX assembly for maximum performance. My point is that, while a boost template should be general purpose, there are some usages that are more relevant than other and some where a general purpose library just doesn't do the job anyway.
That said, I am unlikely to use your library given your current interface. Any fixed-point library without policies allowing for choice in rounding vs. truncation and in saturation vs. wrapping would not meet my needs.
Rounding, etc. is another discussion. I agree that a fixed point should have optional policies for rounding, but I kept rounding and saturation out of the operator discussion to keep it simple. Soren