Couple Thoughts on Infinite precision integer draft

First off, thanks to Maarten for working on this -- it's something that is an important need for many reasons. I'm sorry I haven't had time to keep up with this in real time, but I have a couple thoughts on this proposal. I've tried to review the mail in this thread and mostly what I'm going to say isn't new, but I hope it's enough to help push Maarten to rethink the inheritance aspect of the proposal. 1) Extension by inheritance I believe that this approach is fundamentally flawed. I'll say it even more strongly: I don't believe the library will be accepted into Boost or TR2 with this approach. There are several reasons for this view: a) goes against the current philosophy of c++ standard library b) 'use cases' for runtime/polymorphic extension are minimal c) space efficiency Let's take these one at a time. 1.a) goes against the current philosophy of c++ standard library Outside of iostreams the use of runtime polymorphism in the std library is minimal. The other 'value types' (see Kevlin Henney if you don't know what I mean by this) in the standard library including std::complex and std::string do not support runtime polymorphism. This extends to new decimal number types that are also being proposed for the standard: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n1965.html This should be enough by itself to rethink the approach. The committee isn't likely to go against the wisdom of the past/future in this case. 1.b) 'use cases' for runtime/polymorphic extension are minimal In my experience, a well design value-type usually doesn't need to be extended. 90% of the use cases are just covered. If users need to extend they can either wrap the base type or build their own. Numeric types are the canonical example of a value type. The proposal and discussion on this point have centered on 2 extension examples: the unsigned_integer case and modular_integer. As several people have already pointed out the unsigned_integer example is a flawed example of using inheritance to restrict the behavior of a subtype (see Barbara Liskov and others on what is now known as the Liskov Substitution Principle for more on why this is flawed). The modular_integer strikes me as a completely different type unrelated to infinite integer. I'd also like to echo Dave and others thoughts that an unsigned_integer type is more appropriately coded as a template layered on the base infinite integer. The unsigned integer case is an example of a more general problem of a numeric type with a restricted range. This isn't just a theory, in date-time I use a template called constrained_value to wrap basic numeric types to restrict the range of values -- so for example, you can't construct a month with something outside the range 1-12. Others have extended this approach into very general policy-based frameworks that allow the creation of types with user specified error handling, etc. 1.c) Space efficiency The proposal doesn't really discuss space efficiency, but certainly the introduction of virtual functions guarantees a less space efficient representation. My expectation would be that if I do the following: integer i(0); that, depending on the allocator, the space requirements should be about the same as int i(0); That can't be achieved when the class is polymorphic. Of course this isn't really an issue for a single integer, but applications that use large arrays of integers that are mostly small values will suffer. 2) Allocator interfaces I'm not really an expert on the standard allocator interfaces, but if I understand the approach it makes use of a singleton strategy. That is, there is NO way to set the allocator on an instance by instance basis -- it's global as set by activate/deactivate. (Am I misunderstanding the interface here?) Of course, by itself, this interface is error prone for application design -- if I have 2 different functions and I forget to call deactivate (does that restore the previous allocator?) then I might break another unrelated piece of code. Singletons and global data are a design problem in general, but especially in today's multi-threaded multi-processor environments. Anyway, what needs to be done can likely be templates and I suspect it will result in a superior solution. Jeff
participants (1)
-
Jeff Garland