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
#include
#include
#include
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 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
bool visit(Last, Last, ast::node *, Visitor &)
{
throw "bummer";
}
template
bool visit(First, Last, ast::node * node, Visitor & v)
{
typedef typename mpl::deref<First>::type type;
type * typed_node = dynamic_cast(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;
}