Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explanation of Stroustrup Linearizing Class Hierarchies example

In Stroustrup's C++ Programming Language (4th ed), section 27.4.2 shows a technique to "linearize" a diamond class hierarchy to avoid the overhead of virtual base classes. He starts with the diamond pattern from a real project (Pivot code analyzer tool):

enter image description here

The linear version is drawn as:

enter image description here

and

enter image description here

The code outline is:

namespace ipr {
    struct Node { ... };
    struct Expr : Node { ... };
    struct Stmt : Expr { ... };
    struct Decl : Stmt { ... };
    struct Var : Decl { ... };

    namespace impl {
        template<class T> struct Node : T { ... };
        template<class T> struct Expr : Node<T> { ... };
        template<class S> struct Stmt : S { ... };
        template<class D> struct Decl : Stmt<Expr<D>> { ... };
        struct Var : Decl<ipr::Var> { ... };
    }
}

I'm confused by the irregular structure. Based on the initial description, I was expecting impl to look something like:

namespace impl {
    template<class T> struct Node : T { ... };
    template<class T> struct Expr : Node<T> { ... };
    template<class S> struct Stmt : Expr<S> { ... };
    template<class D> struct Decl : Stmt<D> { ... };
    struct Var : Decl<ipr::Var> { ... };    
}

And I'm thinking the full diagram of these classes is:

enter image description here

My question is, why don't the "interior" three impl template classes have parallel forms, as in my version of the code?

like image 890
xan Avatar asked Jan 18 '15 22:01

xan


1 Answers

My best guess comes from looking at the actual Pivot code which has

template<class D> struct Decl : Stmt<Node<D>> { ... };

instead of Stroustrup's

template<class D> struct Decl : Stmt<Expr<D>> { ... };

That suggests that impl::Stmt doesn't necessarily derive from impl::Expr after all, as in the original diamond diagram (though it still derives from the interface ipr::Expr). It doesn't derive from impl::Expr for Decl and Var, but it does for other implementation classes such as impl::For:

struct For : Stmt<Expr<ipr::For> > { ... }

I'm not sure why Stroustrup didn't explain the irregularity. Perhaps he thought he removed it by changing Stmt<Node> to Stmt<Expr>, or maybe he didn't change it at all (that is, the code changed after he copied it) and he wanted to leave it as is without explaining every detail.

Hopefully a better answer will explain it.

like image 94
xan Avatar answered Sep 21 '22 19:09

xan