-
Modern C++ Design
2003-05-08 00:06 in /books/mcppd
I'm starting to read Modern C++ Design as part of the ALACPP group. 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 acheive 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 aas 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.
Leave a comment
Please use plain text only. No HTML tags are allowed.
Comments are closed for this story.
Trackbacks are closed for this story.