← Back
Editing: variant_functor.hpp
#ifndef PYTHONIC_TYPES_VARIANT_FUNCTOR_HPP #define PYTHONIC_TYPES_VARIANT_FUNCTOR_HPP #include "pythonic/include/types/variant_functor.hpp" #include "pythonic/utils/meta.hpp" #include <utility> #include <cassert> PYTHONIC_NS_BEGIN namespace types { namespace details { template <class Type> variant_functor_impl<Type>::variant_functor_impl(char mem[], Type const &t) : fun(new (mem) Type(t)) { } template <class Type> template <class OtherType> variant_functor_impl<Type>::variant_functor_impl(char mem[], OtherType const &t) : fun(nullptr) { } template <class Type> variant_functor_impl<Type>::variant_functor_impl( char mem[], variant_functor_impl<Type> const &t) : fun(t.fun ? new (mem) Type(*t.fun) : nullptr) { } template <class Type> template <class... OtherTypes> variant_functor_impl<Type>::variant_functor_impl( char mem[], variant_functor_impl<Type, OtherTypes...> const &t) : variant_functor_impl(mem, t.head) { } template <class Type> template <class OtherType, class... OtherTypes> variant_functor_impl<Type>::variant_functor_impl( char mem[], variant_functor_impl<OtherType, OtherTypes...> const &t) : variant_functor_impl(mem, t.tail) { } template <class Type> void variant_functor_impl<Type>::assign(char mem[], variant_functor_impl<Type> const &other) { if (fun != nullptr) fun->~Type(); if (other.fun) fun = new (mem) Type(*other.fun); } template <class Type> void variant_functor_impl<Type>::assign(char mem[], variant_functor<Type> const &other) { assign(mem, static_cast<variant_functor_impl<Type> const &>(other)); } template <class Type> template <class OT0, class OT1, class... OtherTypes> void variant_functor_impl<Type>::assign( char mem[], variant_functor_impl<OT0, OT1, OtherTypes...> const &other) { assign(mem, other.head); assign(mem, other.tail); } template <class Type> template <class OT0, class OT1, class... OtherTypes> void variant_functor_impl<Type>::assign( char mem[], variant_functor<OT0, OT1, OtherTypes...> const &other) { assign(mem, static_cast<variant_functor_impl<OT0, OT1, OtherTypes...> const &>( other)); } template <class Type> template <class OtherType> void variant_functor_impl<Type>::assign( char mem[], variant_functor_impl<OtherType> const &other) { } template <class Type> template <class OtherType> void variant_functor_impl<Type>::assign(char mem[], variant_functor<OtherType> const &other) { } template <class Type> void variant_functor_impl<Type>::assign(char mem[], Type const &other) { if (fun != nullptr) fun->~Type(); fun = new (mem) Type(other); } template <class Type> variant_functor_impl<Type>::~variant_functor_impl<Type>() { if (fun != nullptr) fun->~Type(); } template <class Type> template <class OtherType> void variant_functor_impl<Type>::assign(char mem[], OtherType const &other) { } template <class Type> template <class... Args> auto variant_functor_impl<Type>::operator()(Args &&... args) -> decltype(std::declval<Type>()(std::forward<Args>(args)...)) { assert(fun && "handler defined"); return (*fun)(std::forward<Args>(args)...); } template <class Type> template <class... Args> auto variant_functor_impl<Type>::operator()(Args &&... args) const -> decltype(std::declval<Type>()(std::forward<Args>(args)...)) { assert(fun && "handler defined"); return (*fun)(std::forward<Args>(args)...); } template <class Type, class... Types> template <class... OtherTypes> variant_functor_impl<Type, Types...>::variant_functor_impl( char mem[], OtherTypes const &... t) : head(mem, t...), tail(mem, t...) { } template <class Type, class... Types> template <class... OtherTypes> variant_functor_impl<Type, Types...>::variant_functor_impl( char mem[], variant_functor_impl<OtherTypes...> const &t) : head(mem, t), tail(mem, t) { } template <class Type, class... Types> void variant_functor_impl<Type, Types...>::assign( char mem[], variant_functor_impl<Type, Types...> const &other) { head.assign(mem, other); tail.assign(mem, other); } template <class Type, class... Types> template <class OtherType> void variant_functor_impl<Type, Types...>::assign(char mem[], OtherType const &other) { head.assign(mem, other); tail.assign(mem, other); } template <class Type, class... Types> template <class... Args> auto variant_functor_impl<Type, Types...>::operator()(Args &&... args) -> typename __combined<decltype(std::declval<Type>()(args...)), decltype(std::declval<Types>()(args...))...>::type { if (head.fun) return head(args...); else return tail(args...); } template <class Type, class... Types> template <class... Args> auto variant_functor_impl<Type, Types...>::operator()(Args &&... args) const -> typename __combined<decltype(std::declval<Type>()(args...)), decltype(std::declval<Types>()(args...))...>::type { if (head.fun) return head(args...); else return tail(args...); } } template <class... Types> variant_functor<Types...>::variant_functor(variant_functor const &other) : details::variant_functor_impl<Types...>( mem, static_cast<details::variant_functor_impl<Types...> const &>(other)) { } template <class... Types> variant_functor<Types...> &variant_functor<Types...>:: operator=(variant_functor<Types...> const &other) { details::variant_functor_impl<Types...>::assign(mem, other); return *this; } template <class... Types> template <class... OtherTypes> variant_functor<Types...> &variant_functor<Types...>:: operator=(variant_functor<OtherTypes...> const &other) { details::variant_functor_impl<Types...>::assign(mem, other); return *this; } template <class... Types> template <class OtherType> variant_functor<Types...> &variant_functor<Types...>:: operator=(OtherType const &other) { static_assert( utils::any_of<std::is_same<OtherType, Types>::value...>::value, "consistent assign"); details::variant_functor_impl<Types...>::assign(mem, other); return *this; } template <class... Types> template <class... OtherTypes> variant_functor<Types...>::variant_functor(OtherTypes const &... t) : details::variant_functor_impl<Types...>(mem, t...) { } template <class... Types> template <class... OtherTypes> variant_functor<Types...>::variant_functor( variant_functor<OtherTypes...> const &t) : details::variant_functor_impl<Types...>( mem, static_cast<details::variant_functor_impl<OtherTypes...> const &>( t)) { } } PYTHONIC_NS_END #endif
Save File
Cancel