$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2007-05-23 15:34:39
Scott Meyers wrote:
<...>
> This is passing a runtime parameter to f, but what I want to pass to f is a 
> compile-time type -- the type to dynamically_cast to.  The pointer I'm casting 
> is fixed, so I can bind it into f when I create f.  Am I just missing something?
Here is a modified version of Daniel's code to suit the case from your 
original post (seems it wasn't intended to be a complete solution but 
rather a tutorial on how to implement the recursively inlined iteration 
with the MPL).
Regards,
Tobias
  #include <iostream>
  #include <boost/mpl/vector.hpp>
  #include <boost/mpl/begin_end.hpp>
  #include <boost/mpl/next.hpp>
  #include <boost/mpl/deref.hpp>
  namespace mpl = boost::mpl;
  // a toy model
  namespace ast
  {
    class node
    {
      public:
        virtual ~node() { };
    };
    class expression_node : public node
    { };
    class literal  : public expression_node
    { };
    class operator_node : public node
    { };
    class unary_operator : public operator_node
    { };
    class binary_operator : public operator_node
    { };
    class statement_node : public node
    { };
    class for_loop : public statement_node
    { };
  }
  // a toy visitor
  struct ast_visitor
  {
      typedef mpl::vector<ast::expression_node, ast::operator_node> accepted_types;
      void operator()(ast::expression_node &)
      {
          std::cout << "got an expression_node" << std::endl;
      }
      void operator()(ast::operator_node &)
      {
          std::cout << "got an operator_node" << std::endl;
      }
  };
  // visit facility
  namespace detail
  {
      template <class Last, class Visitor>
      bool visit(Last, Last, ast::node *, Visitor &)
      {
          throw "bummer";
      }
      template <class First, class Last, class Visitor>
      bool visit(First, Last, ast::node * node, Visitor & v)
      {
          typedef typename mpl::deref<First>::type type;
          type * typed_node = dynamic_cast<type *>(node);
          if (! typed_node)
              detail::visit(typename mpl::next<First>::type(), Last(), node, v);
          else
              v(*typed_node);
      }
  }
  template<class Visitor>
  bool visit(ast::node * node, Visitor & with_visitor)
  {
      typedef typename Visitor::accepted_types seq;
      return detail::visit(
          typename mpl::begin<seq>::type()
        , typename mpl::end<seq>::type()
        , node, with_visitor
      );
  }
  int main()
  {
      ast_visitor v;
      {
          ast::literal test;
          visit(& test, v);
      }
      {
          ast::unary_operator test;
          visit(& test, v);
      }
      {
          ast::binary_operator test;
          visit(& test, v);
      }
      {
          try
          {
            ast::for_loop test;
            visit(& test, v);
          }
          catch(...)
          {
            std::cout << "error handling works" << std::endl;
          }
      }
      return 0;
  }