diff --git a/alib2data/src/common/visitor.hpp b/alib2data/src/common/visitor.hpp index 6859fe4c5f0eb40f337b763f6e6eedac0b80d473..45672c001ce99c3ce375dc6c1d46dc6db82ad357 100644 --- a/alib2data/src/common/visitor.hpp +++ b/alib2data/src/common/visitor.hpp @@ -10,294 +10,286 @@ #define VISITOR_H_ #include <stdexcept> +#include <typeindex> namespace std { -// Visitor template declaration -template<typename... Types> + // Visitor template declaration +template < typename ... Types > class visitor; -// specialization for single type -template<typename T> -class visitor<T> { + // specialization for single type +template < typename T > +class visitor < T > { public: - virtual void Visit(void*, T &) const = 0; + virtual void Visit ( void *, T & ) const = 0; }; -// specialization for multiple types -template<typename T, typename... Types> -class visitor<T, Types...> : public visitor<Types...> { + // 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; + // promote the function(s) from the base class + using visitor < Types ... >::Visit; - virtual void Visit(void*, T &) const = 0; + virtual void Visit ( void *, T & ) const = 0; }; -// Visitor template declaration -template<typename... Types> + // Visitor template declaration +template < typename ... Types > class const_visitor; -// specialization for single type -template<typename T> -class const_visitor<T> { + // specialization for single type +template < typename T > +class const_visitor < T > { public: - virtual void Visit(void*, const T &) const = 0; + virtual void Visit ( void *, const T & ) const = 0; }; -// specialization for multiple types -template<typename T, typename... Types> -class const_visitor<T, Types...> : public const_visitor<Types...> { + // specialization for multiple types +template < typename T, typename ... Types > +class const_visitor < T, Types ... > : public const_visitor < Types ... > { public: - // promote the function(s) from the base class - using const_visitor<Types...>::Visit; + // promote the function(s) from the base class + using const_visitor < Types ... >::Visit; - virtual void Visit(void*, const T &) const = 0; + virtual void Visit ( void *, const T & ) const = 0; }; -template<typename... Types> +template < typename ... Types > struct const_promoting_helper; -template<typename Tested, typename... Other> -struct const_promoting_helper<Tested, Other...> { +template < typename Tested, typename ... Other > +struct const_promoting_helper < Tested, Other ... > { - // variant 1 is swaping first and second argument because it came swaped - template<class Desired, class Base, class TargetVisitor, - typename std::enable_if< std::is_constructible<Desired, Tested>::value >::type* = nullptr > - inline static bool tryPromote1(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) { - if(dynamic_cast<const Tested*>(&second)) { - //if(Tested::template typeId<Tested>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment - visitor.Visit(userData, Desired(static_cast<const Tested&>(second)), first); + // variant 1 is swaping first and second argument because it came swaped + template < class Desired, class Base, class TargetVisitor, typename std::enable_if < std::is_constructible < Desired, Tested >::value >::type * = nullptr > + inline static bool tryPromote1 ( void * userData, const Desired & first, const Base & second, const TargetVisitor & visitor ) { + if ( std::type_index ( typeid ( Tested ) ) == std::type_index ( typeid ( second ) ) ) { + visitor.Visit ( userData, Desired ( static_cast < const Tested & > ( second ) ), first ); return true; } else { - return const_promoting_helper<Other...>::tryPromote1(userData, first, second, visitor); + return const_promoting_helper < Other ... >::tryPromote1 ( userData, first, second, visitor ); } } - template<class Desired, class Base, class TargetVisitor, - typename std::enable_if< ! std::is_constructible<Desired, Tested>::value >::type* = nullptr > - inline static bool tryPromote1(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) { - return const_promoting_helper<Other...>::tryPromote1(userData, first, second, visitor); + template < class Desired, class Base, class TargetVisitor, typename std::enable_if < !std::is_constructible < Desired, Tested >::value >::type * = nullptr > + inline static bool tryPromote1 ( void * userData, const Desired & first, const Base & second, const TargetVisitor & visitor ) { + return const_promoting_helper < Other ... >::tryPromote1 ( userData, first, second, visitor ); } - // variant 2 is not swaping first and second argument because it did not came swaped - template<class Desired, class Base, class TargetVisitor, - typename std::enable_if< std::is_constructible<Desired, Tested>::value >::type* = nullptr > - inline static bool tryPromote2(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) { - if(dynamic_cast<const Tested*>(&second)) { - //if(Tested::template typeId<Tested>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment - visitor.Visit(userData, first, Desired(static_cast<const Tested&>(second))); + // variant 2 is not swaping first and second argument because it did not came swaped + template < class Desired, class Base, class TargetVisitor, typename std::enable_if < std::is_constructible < Desired, Tested >::value >::type * = nullptr > + inline static bool tryPromote2 ( void * userData, const Desired & first, const Base & second, const TargetVisitor & visitor ) { + if ( std::type_index ( typeid ( Tested ) ) == std::type_index ( typeid ( second ) ) ) { + visitor.Visit ( userData, first, Desired ( static_cast < const Tested & > ( second ) ) ); return true; } else { - return const_promoting_helper<Other...>::tryPromote2(userData, first, second, visitor); + return const_promoting_helper < Other ... >::tryPromote2 ( userData, first, second, visitor ); } } - template<class Desired, class Base, class TargetVisitor, - typename std::enable_if< ! std::is_constructible<Desired, Tested>::value >::type* = nullptr > - inline static bool tryPromote2(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) { - return const_promoting_helper<Other...>::tryPromote2(userData, first, second, visitor); + template < class Desired, class Base, class TargetVisitor, typename std::enable_if < !std::is_constructible < Desired, Tested >::value >::type * = nullptr > + inline static bool tryPromote2 ( void * userData, const Desired & first, const Base & second, const TargetVisitor & visitor ) { + return const_promoting_helper < Other ... >::tryPromote2 ( userData, first, second, visitor ); } + }; -template<> -struct const_promoting_helper<> { +template < > +struct const_promoting_helper < > { - template<class Desired, class Base, class TargetVisitor> - inline static bool tryPromote1(void*, const Desired&, const Base&, const TargetVisitor&) { return false; } + template < class Desired, class Base, class TargetVisitor > + inline static bool tryPromote1 ( void *, const Desired &, const Base &, const TargetVisitor & ) { return false; } - template<class Desired, class Base, class TargetVisitor> - inline static bool tryPromote2(void*, const Desired&, const Base&, const TargetVisitor&) { return false; } + template < class Desired, class Base, class TargetVisitor > + inline static bool tryPromote2 ( void *, const Desired &, const Base &, const TargetVisitor & ) { return false; } }; -class const_promoting_visitor_base {}; +class const_promoting_visitor_base { }; -// Visitor template declaration -template<typename... Types> + // Visitor template declaration +template < typename ... Types > class const_promoting_visitor; -// specialization for single type -template<typename T> -class const_promoting_visitor<T> : public const_promoting_visitor_base { + // specialization for single type +template < typename T > +class const_promoting_visitor < T > : public const_promoting_visitor_base { public: - virtual void Visit(void*, const T &, const T&) const = 0; - - // variant 1 is swaping first and second argument because it came swaped - template<typename R, typename promoting_helper_type> - bool Visit1(void* userData, const T& first, const R& second) const { - if(dynamic_cast<const T*>(&second)) { - //if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment - this->Visit(userData, static_cast<const T&>(second), first); + virtual void Visit ( void *, const T &, const T & ) const = 0; + + // variant 1 is swaping first and second argument because it came swaped + template < typename R, typename promoting_helper_type > + bool Visit1 ( void * userData, const T & first, const R & second ) const { + if ( std::type_index ( typeid ( T ) ) == std::type_index ( typeid ( second ) ) ) { + this->Visit ( userData, static_cast < const T & > ( second ), first ); return true; } else { - return promoting_helper_type::tryPromote1( userData, first, second, *this ); + return promoting_helper_type::tryPromote1 ( userData, first, second, * this ); } } - // variant 2 is not swaping first and second argument because it did not came swaped - template<typename R, typename promoting_helper_type> - bool Visit2(void* userData, const T& first, const R& second) const { - if(dynamic_cast<const T*>(&second)) { - //if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment - this->Visit(userData, first, static_cast<const T&>(second)); + // variant 2 is not swaping first and second argument because it did not came swaped + template < typename R, typename promoting_helper_type > + bool Visit2 ( void * userData, const T & first, const R & second ) const { + if ( std::type_index ( typeid ( T ) ) == std::type_index ( typeid ( second ) ) ) { + this->Visit ( userData, first, static_cast < const T & > ( second ) ); return true; } else { - return promoting_helper_type::tryPromote2( userData, first, second, *this ); + return promoting_helper_type::tryPromote2 ( userData, first, second, * this ); } } + }; -// specialization for multiple types -template<typename T, typename... Types> -class const_promoting_visitor<T, Types...> : public const_promoting_visitor<Types...> { + // specialization for multiple types +template < typename T, typename ... Types > +class const_promoting_visitor < T, Types ... > : public const_promoting_visitor < Types ... > { public: - // promote the function(s) from the base class - using const_promoting_visitor<Types...>::Visit; - using const_promoting_visitor<Types...>::Visit1; - using const_promoting_visitor<Types...>::Visit2; - - virtual void Visit(void*, const T &, const T&) const = 0; - - // variant 1 is swaping first and second argument because it came swaped - template<typename R, typename promoting_helper_type> - bool Visit1(void* userData, const T& first, const R& second) const { - if(dynamic_cast<const T*>(&second)) { - //if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment - this->Visit(userData, static_cast<const T&>(second), first); + // promote the function(s) from the base class + using const_promoting_visitor < Types ... >::Visit; + using const_promoting_visitor < Types ... >::Visit1; + using const_promoting_visitor < Types ... >::Visit2; + + virtual void Visit ( void *, const T &, const T & ) const = 0; + + // variant 1 is swaping first and second argument because it came swaped + template < typename R, typename promoting_helper_type > + bool Visit1 ( void * userData, const T & first, const R & second ) const { + if ( std::type_index ( typeid ( T ) ) == std::type_index ( typeid ( second ) ) ) { + this->Visit ( userData, static_cast < const T & > ( second ), first ); return true; } else { - return promoting_helper_type::tryPromote1( userData, first, second, *this ); + return promoting_helper_type::tryPromote1 ( userData, first, second, * this ); } } - // variant 2 is not swaping first and second argument because it did not came swaped - template<typename R, typename promoting_helper_type> - bool Visit2(void* userData, const T& first, const R& second) const { - if(dynamic_cast<const T*>(&second)) { - //if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment - this->Visit(userData, first, static_cast<const T&>(second)); + // variant 2 is not swaping first and second argument because it did not came swaped + template < typename R, typename promoting_helper_type > + bool Visit2 ( void * userData, const T & first, const R & second ) const { + if ( std::type_index ( typeid ( T ) ) == std::type_index ( typeid ( second ) ) ) { + this->Visit ( userData, first, static_cast < const T & > ( second ) ); return true; } else { - return promoting_helper_type::tryPromote2( userData, first, second, *this ); + return promoting_helper_type::tryPromote2 ( userData, first, second, * this ); } } + }; -class const_same_visitor_base {}; +class const_same_visitor_base { }; -// Visitor template declaration -template<typename... Types> + // Visitor template declaration +template < typename ... Types > class const_same_visitor; -// specialization for single type -template<typename T> -class const_same_visitor<T> : public const_same_visitor_base { + // specialization for single type +template < typename T > +class const_same_visitor < T > : public const_same_visitor_base { public: - virtual void Visit(void*, const T &, const T&) const = 0; - - template<typename R> - void Visit1(void* userData, const T& first, const R& second) const { - if(dynamic_cast<const T*>(&second)) { - //if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment - this->Visit(userData, first, static_cast<const T&>(second)); - } else { - throw std::logic_error("Same visitor: Visited types are different."); - } + virtual void Visit ( void *, const T &, const T & ) const = 0; + + template < typename R > + void Visit1 ( void * userData, const T & first, const R & second ) const { + if ( std::type_index ( typeid ( T ) ) == std::type_index ( typeid ( second ) ) ) + this->Visit ( userData, first, static_cast < const T & > ( second ) ); + else + throw std::logic_error ( "Same visitor: Visited types are different." ); } + }; -// specialization for multiple types -template<typename T, typename... Types> -class const_same_visitor<T, Types...> : public const_same_visitor<Types...> { + // specialization for multiple types +template < typename T, typename ... Types > +class const_same_visitor < T, Types ... > : public const_same_visitor < Types ... > { public: - // promote the function(s) from the base class - using const_same_visitor<Types...>::Visit; - using const_same_visitor<Types...>::Visit1; - - virtual void Visit(void*, const T &, const T&) const = 0; - - template<typename R> - void Visit1(void* userData, const T& first, const R& second) const { - if(dynamic_cast<const T*>(&second)) { - //if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment - this->Visit(userData, first, static_cast<const T&>(second)); - } else { - throw std::logic_error("Same visitor: Visited types are different."); - } + // promote the function(s) from the base class + using const_same_visitor < Types ... >::Visit; + using const_same_visitor < Types ... >::Visit1; + + virtual void Visit ( void *, const T &, const T & ) const = 0; + + template < typename R > + void Visit1 ( void * userData, const T & first, const R & second ) const { + if ( std::type_index ( typeid ( T ) ) == std::type_index ( typeid ( second ) ) ) + this->Visit ( userData, first, static_cast < const T & > ( second ) ); + else + throw std::logic_error ( "Same visitor: Visited types are different." ); } + }; -template<typename T, typename... Types> +template < typename T, typename ... Types > class acceptor_base { public: - typedef visitor<Types...> visitor_type; + typedef visitor < Types ... > visitor_type; - typedef const_visitor<Types...> const_visitor_type; + typedef const_visitor < Types ... > const_visitor_type; - typedef const_promoting_visitor<Types...> const_promoting_visitor_type; - typedef const_promoting_helper<Types...> const_promoting_helper_type; + typedef const_promoting_visitor < Types ... > const_promoting_visitor_type; + typedef const_promoting_helper < Types ... > const_promoting_helper_type; - typedef const_same_visitor<Types...> const_same_visitor_type; + typedef const_same_visitor < Types ... > const_same_visitor_type; typedef T base_type; + virtual void Accept ( void * userData, const visitor < Types ... > & visitor ) = 0; - virtual void Accept(void* userData, const visitor<Types...>& visitor) = 0; + virtual void Accept ( void * userData, const const_visitor < Types ... > & visitor ) const = 0; - virtual void Accept(void* userData, const const_visitor<Types...>& visitor) const = 0; + virtual bool Accept ( void * userData, const T & other, const const_promoting_visitor < Types ... > & visitor, bool swap ) const = 0; - virtual bool Accept(void* userData, const T& other, const const_promoting_visitor<Types...>& visitor, bool swap) const = 0; - - virtual void Accept(void* userData, const T& other, const const_same_visitor<Types...>& visitor) const = 0; + virtual void Accept ( void * userData, const T & other, const const_same_visitor < Types ... > & visitor ) const = 0; }; -template<typename Derived, typename AcceptorBase, typename Base> +template < typename Derived, typename AcceptorBase, typename Base > class acceptor : public Base { public: using Base::Accept; - virtual void Accept(void* userData, const typename AcceptorBase::visitor_type& visitor) { - visitor.Visit(userData, static_cast<Derived&>(*this)); + virtual void Accept ( void * userData, const typename AcceptorBase::visitor_type & visitor ) { + visitor.Visit ( userData, static_cast < Derived & > ( * this ) ); } - virtual void Accept(void* userData, const typename AcceptorBase::const_visitor_type& visitor) const { - visitor.Visit(userData, static_cast<const Derived&>(*this)); + virtual void Accept ( void * userData, const typename AcceptorBase::const_visitor_type & visitor ) const { + visitor.Visit ( userData, static_cast < const Derived & > ( * this ) ); } - virtual bool Accept(void* userData, const typename AcceptorBase::base_type& other, const typename AcceptorBase::const_promoting_visitor_type& visitor, bool swap) const { - if(swap) { - // variant 1 is swaping first and second argument because it came swaped - return visitor.template Visit1<typename AcceptorBase::base_type, typename AcceptorBase::const_promoting_helper_type>(userData, static_cast<const Derived&>(*this), other); - } else { - // variant 2 is not swaping first and second argument because it did not came swaped - return visitor.template Visit2<typename AcceptorBase::base_type, typename AcceptorBase::const_promoting_helper_type>(userData, static_cast<const Derived&>(*this), other); - } + virtual bool Accept ( void * userData, const typename AcceptorBase::base_type & other, const typename AcceptorBase::const_promoting_visitor_type & visitor, bool swap ) const { + if ( swap ) + // variant 1 is swaping first and second argument because it came swaped + return visitor.template Visit1 < typename AcceptorBase::base_type, typename AcceptorBase::const_promoting_helper_type > ( userData, static_cast < const Derived & > ( * this ), other ); + else + // variant 2 is not swaping first and second argument because it did not came swaped + return visitor.template Visit2 < typename AcceptorBase::base_type, typename AcceptorBase::const_promoting_helper_type > ( userData, static_cast < const Derived & > ( * this ), other ); } - virtual void Accept(void* userData, const typename AcceptorBase::base_type& other, const typename AcceptorBase::const_same_visitor_type& visitor) const { - visitor.template Visit1<typename AcceptorBase::base_type>(userData, static_cast<const Derived&>(*this), other); + virtual void Accept ( void * userData, const typename AcceptorBase::base_type & other, const typename AcceptorBase::const_same_visitor_type & visitor ) const { + visitor.template Visit1 < typename AcceptorBase::base_type > ( userData, static_cast < const Derived & > ( * this ), other ); } + }; -template<class T, class R, - typename std::enable_if< std::is_base_of< const_same_visitor_base, R >::value >::type* = nullptr > -void Accept(void* userData, const T& first, const T& second, const R& visitor) { - first.Accept(userData, second, visitor); +template < class T, class R, typename std::enable_if < std::is_base_of < const_same_visitor_base, R >::value >::type * = nullptr > +void Accept ( void * userData, const T & first, const T & second, const R & visitor ) { + first.Accept ( userData, second, visitor ); } -template<class T, class R, - typename std::enable_if< std::is_base_of< const_promoting_visitor_base, R >::value >::type* = nullptr > -void Accept(void* userData, const T& first, const T& second, const R& visitor) { +template < class T, class R, typename std::enable_if < std::is_base_of < const_promoting_visitor_base, R >::value >::type * = nullptr > +void Accept ( void * userData, const T & first, const T & second, const R & visitor ) { bool res; - // variant 2 is swaping first and second argument because it come swaped - res = first.Accept(userData, second, visitor, false); - if(res) return; - // variant 1 is not swaping first and second argument because it did not come swaped - res = second.Accept(userData, first, visitor, true); - if(res) return; + // variant 2 is swaping first and second argument because it come swaped + res = first.Accept ( userData, second, visitor, false ); + + if ( res ) return; + + // variant 1 is not swaping first and second argument because it did not come swaped + res = second.Accept ( userData, first, visitor, true ); + + if ( res ) return; - throw std::logic_error("Promoting visitor: Can't promote one parameter to type of the other."); + throw std::logic_error ( "Promoting visitor: Can't promote one parameter to type of the other." ); } } /* namespace std */