Re: паттерн посетитель (Visitor)
От: Abyx Россия  
Дата: 06.06.11 22:33
Оценка:
применив немножко MPL, получил следующее:

#include <boost/mpl/vector.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/distance.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>

struct visitor
{
    typedef boost::mpl::vector<
        some,
        other
    >::type types;

    template<class Impl>
    visitor(Impl* impl) : impl(impl), onVisit(&ImplWrap<Impl>::on_visit) {}

    template<typename T>
    void visit(T& obj)
    {
        typedef typename boost::mpl::find<types, T>::type iter;
        const int idx = boost::mpl::distance<boost::mpl::begin<types>::type, iter>::type::value; //iter::pos::value; ???
        onVisit(impl, obj, idx);
    }

    template<class Impl>
    struct ImplWrap
    {
        typedef void (*call_visit_fn_t)(Impl& impl, node& el);

        template<int idx>
        static void call_visit(Impl& impl, node& obj)
        {
            impl(static_cast<boost::mpl::at_c<types, idx>::type&>(obj));
        }

        template<int idx>
        static bool fill_item(call_visit_fn_t* table)
        {
            table[idx - 1] = &call_visit<idx - 1>;
            return fill_item<idx - 1>(table);
        }

        template<>
        static bool fill_item<0>(call_visit_fn_t*)
        {
            return 0;
        }

        static void on_visit(void* impl, node& obj, int typeIdx)
        {
            static const size_t tableSize = boost::mpl::size<types>::value;

            static call_visit_fn_t table[tableSize];
            static bool tableInitialized = fill_item<tableSize>(table);
            
            table[typeIdx](*(Impl*)impl, obj);
        }
    };

    void* impl;
    void (*onVisit)(void* impl, node& obj, int typeIdx);
};

template<class Vis>
inline void apply_visitor(Vis& vis, node* n)
{
    visitor impl(&vis);
    n->accept(&impl);
}


gcc это компилить отказывается (и за специализации fill_item внутри класса) (тот который на codepad.org), а MSVC2010 компилит нормально

выглядит это страшно, хоть и без макросов, но всёравно страшно.
может можно как-то упростить, с тем же С++0х (которое есть в MSVC)
In Zen We Trust
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.