a small improvement around the cyclic visitor

Developers
2008-08-14
2013-04-08
  • Hello guys,

    I've been working with the cyclic visitor from loki and I decided to make it a little more friendly. I can never remember boolean flags so I added an enumerated type that defines the behavior of the visitor. I also added another template parameter to specify if the visitor is strict or non-strict. In this way, I use the visitor as follows:

    typedef Visitor<ReturnType, TypeList, Strict, Mutable> vis1; // compiler complaints if any Visit(T&) is not defined
    typedef Visitor<ReturnType, TypeList, Nonstrict, Immutable> vis1; // default behavior for not defined Visit(const T&)

    Now, it would be nice also to choose a different behavior for the non-strict visitor instead of just returning the default value for the ReturnType, but I haven't done that yet (maybe a template template parameter).

    It's not a huge improvement, but I thought that it would be nice to hear some feedback from other people working with the library.

    Best regards,

    Alejandro M. Aragón

    #ifndef VISITOR_HPP_
    #define VISITOR_HPP_

    #include <Loki/Typelist.h>

    namespace loki {

    using Loki::NullType;
    using Loki::Typelist;

    enum Visit_type { Strict, Nonstrict, Mutable, Immutable };

    template <class T, typename R = void, Visit_type = Mutable>
    class StrictVisitor;

    template <class T, typename R>
    class StrictVisitor<T, R, Mutable>
    {
    public:
        typedef R ReturnType;
        typedef T ParamType;
        virtual ~StrictVisitor() {}
        virtual ReturnType Visit(ParamType&) = 0;
    };

    template <class T, typename R>
    class StrictVisitor<T, R, Immutable>
    {
    public:
        typedef R ReturnType;
        typedef const T ParamType;
        virtual ~StrictVisitor() {}
        virtual ReturnType Visit(ParamType&) = 0;
    };

    /// class template StrictVisitor (specialization)

    template <class Head, class Tail, typename R>
    class StrictVisitor<Typelist<Head, Tail>, R, Mutable>
    : public StrictVisitor<Head, R, Mutable>, public StrictVisitor<Tail, R, Mutable>
    {
    public:
        typedef R ReturnType;
        typedef Head ParamType;
    };

    template <class Head, typename R>
    class StrictVisitor<Typelist<Head, NullType>, R, Mutable> : public StrictVisitor<Head, R, Mutable>
    {
    public:
        typedef R ReturnType;
        typedef Head ParamType;
        using StrictVisitor<Head, R, Mutable>::Visit;
    };

    template <class Head, class Tail, typename R>
    class StrictVisitor<Typelist<Head, Tail>, R, Immutable>
    : public StrictVisitor<Head, R, Immutable>, public StrictVisitor<Tail, R, Immutable>
    {
    public:
        typedef R ReturnType;
        typedef Head ParamType;
    };

    template <class Head, typename R>
    class StrictVisitor<Typelist<Head, NullType>, R, Immutable> : public StrictVisitor<Head, R, Immutable>
    {
    public:
        typedef R ReturnType;
        typedef Head ParamType;
        using StrictVisitor<Head, R, Immutable>::Visit;
    };

    ////////////////////////////////////////////////////////////////////////////////
    // class template NonStrictVisitor
    // Implements non-strict visitation (you can implement only part of the Visit
    //     functions)
    ////////////////////////////////////////////////////////////////////////////////

    template <class T, typename R = void, Visit_type V = Mutable> class BaseVisitorImpl;

    template <class Head, class Tail, typename R, Visit_type V>
    class BaseVisitorImpl<Typelist<Head, Tail>, R, V>
    : public StrictVisitor<Head, R, V>, public BaseVisitorImpl<Tail, R, V> {
    public:
        typedef typename StrictVisitor<Head, R, V>::ParamType ParamType;
        virtual R Visit(ParamType& h)
        { return R(); }
    };

    template <class Head, typename R, Visit_type V>
    class BaseVisitorImpl<Typelist<Head, NullType>, R, V> : public StrictVisitor<Head, R, V>
    {
    public:
        typedef typename StrictVisitor<Head, R, V>::ParamType ParamType;
        virtual R Visit(ParamType& h)
        { return R(); }
    };

    /// Visitor

    template <typename R, class TList, Visit_type U = Strict, Visit_type V = Mutable>
    class Visitor;

    template <typename R, class TList,  Visit_type V>
    class Visitor<R, TList, Strict, V> : public StrictVisitor<TList, R, V> {
    public:
        typedef R ReturnType;

        template <class Visited>
        ReturnType GenericVisit(Visited& host) {
            StrictVisitor<Visited, ReturnType, V>& subObj = *this;
            return subObj.Visit(host);
        }
    };

    template <typename R, class TList,  Visit_type V>
    class Visitor<R, TList, Nonstrict, V> : public BaseVisitorImpl<TList, R, V> {
    public:

        typedef R ReturnType;

        template <class Visited>
        ReturnType GenericVisit(Visited& host) {
            StrictVisitor<Visited, ReturnType, V>& subObj = *this;
            return subObj.Visit(host);
        }
    };

    } // namespace visitor

    #endif /* VISITOR_HPP_ */