Wednesday, April 10, 2013

Emacs tip: Use 'view-lossage' to answer the question "How did that happen?"

Does it ever happen that you are thumping along in emacs, and suddenly you are in a mode or buffer that you never knew about before?  You must have unintentionally hit some keystroke that caused the change, but what was it?

You can find the answer by typing C-h l (that's a little "L"). This runs view-lossage, which shows the last 100 characters typed.

For instance, this morning I was suddenly staring at a blank buffer called "ChangeLog". What is that thing? To find out, I typed C-h l. A *Help* buffer opened with a few lines of symbols. Here are the last couple lines:

C-s F I X M E C-a C-n C-n C-n C-n C-n C-n C-n
C-n C-x 2 C-x o C-x V a r C-x u C-h l

You start reading the lossage at the end.  So, at the end I can see the C-h l from invoking view-lossage.  Right before that, an undo (C-x u) to get rid of the typing I had just done into the unknown ChangeLog buffer.  Right before that, C-x V a r.  Ah, I meant to search for "Var", but I must have hit C-x instead of C-s.  This is the culprit.

So what do those keys do?  It opened a new buffer, but did it have some other harmful side-effect I want to know about?  Hit C-h k to start the describe-key function, and start typing C-x, v, a.  Before I could type the 'r', the *Help* buffer showed up and explained that I had entered the keystroke for vc-update-change-log, a function that seems like it was more useful back in the days of RCS than today, but which doesn't harm anything else.  Anyway, mystery solved!

There tend to be two situations in which I call view-lossage.  Number one is where I think, "Hmm, I don't know what I did, but it might be useful."  For that case, view-lossage lets you explore that functionality.  That was the case this morning with ChangeLog; I was curious about it but it turned out not to be useful to me.  Number two is where I think "I don't ever want that to happen again".  In that case, figure out the offending keystroke, and then disable it in your .emacs file, like this:

(global-unset-key "\C-[\C-[") ;; prefix-command
(global-unset-key "\C-x\C-p") ;; mark-page
(global-unset-key "\C-x\C-n") ;; set-goal-column

Those are typos I've made before that have annoying effects, so I just completely disable those keystrokes  (mark-page is especially nasty: it sets the mark at the end of the file, and moves the point to the beginning of the file, so there's not always an easy way to jump back to where you were in the file).

Friday, January 25, 2013

C++ Private Inheritance

For a long time I believed private inheritance was such an arcane feature that it should be avoided. In my C++ Coding Standard, 8.2 stated "Use only public inheritance." Here was my rationale:

You might find private or protected inheritance useful to save a few lines of code somewhere. But I claim you should just duplicate the lines of code, rather than couple together classes which are so different conceptually that public inheritance can't be used. They might be structurally the same today, but if they are conceptually different, that structural similarity may change over time and give you a huge headache.

I think that rationale is pretty good, but now I've decided it might be worthwhile to use private inheritance in some cases. For instance, it might make sense to inherit from some STL container class, and promote some of its lookup functions or subtypes to "public" with "using" declarations. Like this:

  class Foo : private std::map<int, Bar *> {

  public:
    typedef std::map<int, Bar *> Base;
    using Base::key_type;
    using Base::data_type;
    using Base::value_type;
    using Base::const_iterator;
    using Base::begin;
    using Base::end;
    using Base::empty;
    using Base::size;
    using Base::find;

The likelihood of the structural change mentioned above is very low in this case, and the "using" declarations -- which I'll admit I didn't know could be used that way when I first wrote the standard -- allow you to reuse worthwhile parts of the base class in a very clean and foolproof manner. Later if you realize there's another bit of functionality you want to expose publicly, you only have to write a one-liner, not a wrapper function. Meanwhile, things you might not want exposed -- like operator[]() -- stay out of the interface.

But the clincher for me is that you had better not inherit publicly from a class like std::map.  Why?  Because it doesn't have a virtual destructor.  What if someone -- for whatever reason -- ends up with a pointer to a std::map which is actually one of your Foo objects, and wants to delete it?  Only the map destructor will be called.  If ~Foo() was supposed to delete its values, that won't happen.  Similarly, public inheritance means that someone could take a pointer to a Foo, and then use map's copy constructor or assignment operator to make a simple pointer copy of the Foo, perhaps unintentionally.  Then if the original was deleted, and deleted its values, the copy would hold stale pointers.

Interestingly, I didn't seem very worried about that situation when I annotated the standard.  I wrote that you might sometimes break 8.4 -- "Destructors of base classes must be pure virtual (but implemented)." -- giving this bad advice:

If you have a memory-sensitive class where subclasses will not be used polymorphically (or do not require polymorphic destruction), you can disregard the rule and get rid of the virtual table pointer.

That seems ridiculous now.  That is actually exactly the use case for private inheritance:  you want to reuse some code, but not polymorphically.

This all came to the fore today when I considered making a class 'public std::pair', so it could model an Edge in a Boost Graph Library edge_list<>, which requires 'first' and 'second' members (at least in the iterator class you instantiate edge_list<> with).  But recently a friend of mine had twitted me on another class I wrote that inherits publicly from an STL container, so I started to think about these issues.

I'm still not sure how I'll implement my Edge class -- except that it won't be public pair -- but I see that I need to change the coding standard someday soon, to reflect the reasonable usage of private inheritance.