Kevin Scaldeferri on 5 Jun 2003 21:44:01 -0000 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
[ALACPP] Notes -- Chapter 1 |
Figured I might as well post previous notes that I made in my journal. Might provoke some discussion or be useful to people who missed particular meetings. Chapter 1 I'm starting to read Modern C++ Design as part of the ALACPP group (soon to be at http://www.alacpp.org/, but not yet). It's a bit of an adventure given that my C++ experience is limited to a couple quarters in school. We're reading the first chapter for tomorrow, which is an intro to advanced generics/templates using the concept of policies. I haven't quite grokked it fully, but I'm starting to get an idea of where this technique fits in. The shortcomings of simple multiple inheritance are well-known. It's brittle and doesn't scale well, nor is it flexible enough to really deal with non-trivial interweaving of the constituents. Standard pattern-based OO design generally prescribes composition rather than inheritance to achieve flexibility and scalability. At a first glance, policies look a lot like the Strategy pattern. However, the differences are the interesting bit. First, and probably least importantly, the syntax is more concise for templated policies that for setting a bunch of strategies. Also, C++ typedefs can simplify your life, although factory methods are essentially semantically equivalent, if a litte more verbose. Second, templates provide compile-time type safety, which isn't present with a strategy. This means that you can't accidentally assign a single-threaded instance of your class where you really needed a multi-threaded design, because the compiler will give a error. Also, because templates provide compile-time binding, there are performance benefits. The tradeoff is a slight loss of flexibility as you can't change a policy in the course of execution the way you can a strategy. (Actually, this is not quite true. Alexandrescu talks a little bit about how to specify allowed type conversions between policies, but I haven't managed to absorb that section yet.) The most intriguing difference to me at this point is way that you can deal with optional features of the policy. In a language like Java (pre-generics) you have to deal with this in one of two ways. Either you include optional methods in your policy interface and permit the hated UnsupportedOperationException, or you stick the optional methods into a subinterface and deal with a lot of "instanceof" checks, which also tend to make people ill. However, two features of C++ make another option availible. First, the enhanced compile-time typing means that the runtime UnsupportedOperationExceptions turn into compiler errors. Second, the compiler doesn't actually enforce type-checking on methods which are never used! So, you can include methods which rely on optional features of a policy, but if a user of your class configures it with a policy that doesn't support them but doesn't use those methods of your class either, the compiler doesn't complain! Conversely, if they use a methods which relies on a feature their choice of policy doesn't allow, that is a compile-time error. That's pretty wild. I'm not sure if I like it, but it's definitely a little mind-boggling. ... A continutation from where I left off last night... The mind-boggling nature of this (optional interface features without ugly type checks or exceptions) isn't the fact that you can do it. Perl and Smalltalk programmers are immediately familiar with this form of polymorphism (interface polymorphism) (and the associated runtime errors when you screw up). Lispers would say, "Variables don't (shouldn't) have types, values have types". However, strongly typed languages like Java and C++ usually lock you into inheritance polymorphism. (Despite Java's use of the term "interface", it does not imply the same flexibility.) The magic here is interface polymorphism with compile-time type checking. At some point I'll have to think more about type-inferring languages like OCaml and how exactly things work there. I'm not sure if that compiler will allow you the same flexibility and safety as the C++ template technique. _______________________________________________ alacpp mailing list alacpp@xxxxxxxxxxx http://lists.ellipsis.cx/mailman/listinfo/alacpp