Visitor パターンの欠点というか、面倒な要素のひとつとして、 ConcreteElement の全てに Accept メソッドを用意しなくてはならない、というものがあります。基底クラスでこれをやってしまうと、 Visitor クラスに渡される型が全て基底クラスのものになってしまうため、これは一見避けられない問題のに見えますが、 C++ の場合テンプレートを使用すれば避けることができます。 Design Patterns for Generic Programming in C++ を読んで気付きました。
以前ここでも紹介した基底クラスに自分 (具象クラス) の型を教えるイディオムを使用すれば良い。
template<class T> class element { public: element() {} virtual element() {} void accept(visitor& v) { v.visit(static_cast<T&>(*this)); } }; class concrete_element : public element<concrete_element> { // ...略 }; // visitor も略
基底クラスの Accept の中で具象クラスへのキャストを行ってから Visitor へ渡すため、ダブルディスパッチを正常に動作させることができるようになります。
いま MC++D の Visitor の章を読んでいるのですが、このイディオムを適用すればここで紹介されている非循環式 Visitor の実装にある DEFINE_VISITABLE マクロや dynamic_cast は消せるのではないか? と思いました。後で、試してみたいと思います。