Boost logo

Boost Users :

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;
  }


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net