#ifndef QLOW_VISITOR_H #define QLOW_VISITOR_H namespace qlow { template<typename R, typename... T> class Visitor; template<typename R> class Visitor<R> { public: using ReturnType = R; }; template<typename R, typename T> class Visitor<R, T> : public Visitor<R> { public: using ReturnType = R; virtual R visit(T& arg) = 0; }; template<typename R, typename T, typename... V> class Visitor<R, T, V...> : public Visitor<R, V...> { public: using Visitor<R, V...>::visit; using ReturnType = R; virtual R visit(T& arg) = 0; }; template<typename RT, typename V> class Visitable { public: virtual ~Visitable(void) {} virtual RT accept(V& visitor) = 0; }; // // template<class T> // class Visitable // { // public: // template<typename Visitor> // void accept(Visitor& v) // { // v.visit(static_cast<T&>(*this)); // } // }; // // //// Visitor template declaration //template<typename... Types> //class Visitor; // //// specialization for single type //template<typename T> //class Visitor<T> { //public: // virtual void visit(T & visitable) = 0; //}; // //// specialization for multiple types //template<typename T, typename... Types> //class Visitor<T, Types...> : public Visitor<Types...> { //public: // // promote the function(s) from the base class // using Visitor<Types...>::visit; // // virtual void visit(T & visitable) = 0; //}; // //template<typename... Types> //class Visitable { //public: // virtual void accept(Visitor<Types...>& visitor) = 0; //}; // //template<typename Derived, typename... Types> //class VisitableImpl : public virtual Visitable<Types...> { //public: // virtual void accept(Visitor<Types...>& visitor) { // visitor.visit(static_cast<Derived&>(*this)); // } //}; // #if 0 template<typename... T> class Visitor; template<> class Visitor<> { public: }; template<typename T> class Visitor<T> : public Visitor<> { public: virtual void visit(T& arg) = 0; }; template<typename T, typename... V> class Visitor<T, V...> : public Visitor<V...> { public: using Visitor<V...>::visit; virtual void visit(T& arg) = 0; }; // // template<typename VT> // class VisitableBase // { // public: // virtual typename VisitorType::ReturnType accept(VisitorType& visitor); // }; // template<typename VT> class VisitableBase { // public: // using VisitorType = VT; // typename VisitorType::ReturnType accept(VisitorType& visitor) // { // return visitor.visit(static_cast<T&>(*this)); // } public: template <typename T> void accept(T& visitor) { visitor.visit(static_cast<VT&>(*this)); } }; #endif } #endif // QLOW_VISITOR_H