8

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?

T.C.
  • 133,968
  • 17
  • 288
  • 421
xan
  • 7,511
  • 2
  • 32
  • 45

1 Answers1

2

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.

xan
  • 7,511
  • 2
  • 32
  • 45