nice clean sound
My iPod earphones went through the wash yesterday. Oops. Slightly to my surprise, they sound just about the same afterwards as they did before.
I suppose this is what they call a blog. Except that blogs are supposed to be updated more often than this is.
Feeds: Atom 1.0 (preferred), RSS 0.91. Front page: link.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
My iPod earphones went through the wash yesterday. Oops. Slightly to my surprise, they sound just about the same afterwards as they did before.
More mindless link propagation. This has been done before, but never half so well: The good folk of Making Light turn spam into poetry. I believe the approved response is spelt "Squeeeeeee!".
Out this evening to an excellent dinner chez Sarah C. Unfortunately, at some point during the evening someone seems to have decided that s/he needed my bicycle saddle more than I did. Ah, well.
So, I have this C++ program with a class that among its other responsibilities needs to interpret textual commands from a user.
class BallOfMud {
...
struct command {
string command_name;
string arg_spec;
bool (BallOfMud::*func)(stuff);
};
...
};
The command implementation functions are represented here as pointer-to-member so that they can act on the relevant class instance.
I find that the class has grown too big and diffuse, and decide
to split it into two more coherent ones. Each of the two will
be responsible for handling some of the commands. Time to split
off a CommandInterpreter class, then.
Spotted the problem yet? No? Well...
class CommandInterpreter {
...
struct command {
string command_name;
string arg_spec;
bool (CommandInterpreter::*func)(stuff);
};
...
};
class PerfectlyFormedJewel : public CommandInterpreter { ... };
Now C++'s type soundness rules say that you can't store a
PerfectlyFormedJewel::* in a space designed for a
CommandInterpreter::*. Why? Because the latter has
to be able to do the right thing when called with any instance
of CommandInterpreter pointed to by this,
whereas the former might rely on being given an instance of
PerfectlyFormedJewel. Aargh!
The "solution" (familiar to old C++ hands) is "Coplien's curiously recurring template pattern", whereby an instantiation of a class template can have one of its own subclasses as a template parameter:
template<typename T>
class CommandInterpreter {
struct command {
bool (T::*func)(...);
};
};
class PerfectlyFormedJewel : public CommandInterpreter<PerfectlyFormedJewel> { ... };
Only you really want to make CommandInterpreter<T>
inherit (excuse me, derive; this is C++, and it would never do to use standard
terminology) from a non-templated superbase class, so that
you don't have to put all the implementation of the damn thing
into the public interface. (And also, in this particular case, for other
reasons I shan't go into.) And don't get me started on what happens when
you want one of these perfectly formed jewels to have subclasses of its
own.
The tragic thing is that once C++ programmers are really well
house-trained, their reaction on first seeing something like this
is "Cool! A templated class can have one of its own subclasses
as a template parameter! Just think of all the
confusingsophisticated things
we can do with that!", when it ought to be "What kind of idiot
language requires you to put up with this kind of nonsense?".