← Back
Editing: variant_functor.hpp
#ifndef PYTHONIC_INCLUDE_TYPES_VARIANT_FUNCTOR_HPP #define PYTHONIC_INCLUDE_TYPES_VARIANT_FUNCTOR_HPP #include "pythonic/include/utils/meta.hpp" #include "pythonic/include/types/combined.hpp" #include <utility> PYTHONIC_NS_BEGIN namespace types { /* Variant functor is a generic wrapper for functor object, for which we *don't know a priori the common signature, * because of of the variadic operator(). * * The trick is to allocate a piece of memory large enough to hold any of *the functor, then maintain, for each functor type, a pointer to that type. * There can be only one pointer for each variadic set to a non null value *(based on the preallocated memory buffer). * * When calling the functor operator(), the code iterates (linearly) on each *pointer && call the operator() of this pointer. */ template <class... Types> struct variant_functor; namespace details { template <class... Types> struct variant_functor_impl; template <class Type> struct variant_functor_impl<Type> { Type *fun = nullptr; variant_functor_impl() = default; variant_functor_impl(variant_functor_impl const &) = delete; ~variant_functor_impl(); variant_functor_impl(char mem[], Type const &t); variant_functor_impl(char mem[], variant_functor_impl<Type> const &t); template <class... OtherTypes> variant_functor_impl(char mem[], variant_functor_impl<Type, OtherTypes...> const &t); template <class OtherType, class... OtherTypes> variant_functor_impl( char mem[], variant_functor_impl<OtherType, OtherTypes...> const &t); template <class OtherType> variant_functor_impl(char mem[], OtherType const &t); variant_functor_impl &operator=(variant_functor_impl const &) = delete; void assign(char mem[], variant_functor_impl const &); void assign(char mem[], variant_functor<Type> const &); void assign(char mem[], Type const &); template <class OtherType> void assign(char mem[], OtherType const &); template <class OT0, class OT1, class... OtherTypes> void assign(char mem[], variant_functor_impl<OT0, OT1, OtherTypes...> const &); template <class OT0, class OT1, class... OtherTypes> void assign(char mem[], variant_functor<OT0, OT1, OtherTypes...> const &); template <class OtherType> void assign(char mem[], variant_functor_impl<OtherType> const &); template <class OtherType> void assign(char mem[], variant_functor<OtherType> const &); template <class... Args> auto operator()(Args &&... args) -> decltype(std::declval<Type>()(std::forward<Args>(args)...)); template <class... Args> auto operator()(Args &&... args) const -> decltype(std::declval<Type>()(std::forward<Args>(args)...)); }; template <class Type, class... Types> struct variant_functor_impl<Type, Types...> { variant_functor_impl<Type> head; variant_functor_impl<Types...> tail; variant_functor_impl() = default; variant_functor_impl(variant_functor_impl const &) = delete; template <class... OtherTypes> variant_functor_impl(char mem[], OtherTypes const &... t); template <class... OtherTypes> variant_functor_impl(char mem[], variant_functor_impl<OtherTypes...> const &t); variant_functor_impl &operator=(variant_functor_impl const &) = delete; void assign(char mem[], variant_functor_impl const &); template <class OtherType> void assign(char mem[], OtherType const &); template <class... Args> auto operator()(Args &&... args) -> typename __combined< decltype(std::declval<Type>()(args...)), decltype(std::declval<Types>()(args...))...>::type; template <class... Args> auto operator()(Args &&... args) const -> typename __combined< decltype(std::declval<Type>()(args...)), decltype(std::declval<Types>()(args...))...>::type; }; } template <class... Types> struct variant_functor : details::variant_functor_impl<Types...> { using callable = void; // memory used to initialize the actual functor // default construction cannot be used because generator are not // default-constructible char mem[utils::max_element<sizeof(Types)...>::value]; variant_functor() = default; variant_functor(variant_functor const &); variant_functor &operator=(variant_functor const &); template <class OtherType> variant_functor &operator=(OtherType const &); template <class... OtherTypes> variant_functor &operator=(variant_functor<OtherTypes...> const &); template <class... OtherTypes> variant_functor(OtherTypes const &... t); template <class... OtherTypes> variant_functor(variant_functor<OtherTypes...> const &t); }; } PYTHONIC_NS_END #endif
Save File
Cancel