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