diff --git a/types/tagged.hpp b/types/tagged.hpp index fdc8a51b..f14ce306 100644 --- a/types/tagged.hpp +++ b/types/tagged.hpp @@ -162,46 +162,31 @@ namespace std { namespace cruft { namespace detail { - // If the tagged object matches the IndexV'th type in ComponentsT then - // invoke visitor with the object as the argument. Else, advance to - // the next index and try with that type. - // - // We assume that outside callers only call this function with an - // IndexV of 0 (so that we have assurances that every type is visited). - template < - std::size_t IndexV, - typename VisitorT, - typename TaggedT - > + template + requires ( + std::is_invocable_v< + VisitorT, + decltype (std::declval ().template get ()) + > + ) decltype (auto) - visit ( - VisitorT &&visitor, - TaggedT &&arg - ) { - static_assert (IndexV < std::tuple_size_v>); - using nth_t = std::tuple_element_t>; - - // If we're the last valid index then we must be invoked because - // there's no other option. Do this, and (statically) avoid - // further recursion. - if constexpr (IndexV + 1 == std::tuple_size_v>) { - return std::invoke (visitor, arg.template get ()); + visit (VisitorT &&visitor, TaggedT &&arg) + { + if constexpr (sizeof ...(TailT) == 0) { + return std::invoke (std::forward (visitor), arg.template get ()); } else { - // If the tag matches, then dispatch, else recurse with the - // next available type index. - if (arg.tag () == nth_t::tag) { - return std::invoke (visitor, arg.template get ()); + if (arg.tag () == HeadT::tag) { + return std::invoke (std::forward (visitor), arg.template get ()); } else { - return visit ( - std::forward (visitor), - arg - ); + return visit (std::forward (visitor), arg); } } } } + /// Call the invokable `VisitorT` with the value in the supplied tagged + /// union. template < typename VisitorT, template typename TaggedT, @@ -216,13 +201,15 @@ namespace cruft { { static_assert (sizeof...(ComponentsT)); - return detail::visit<0> ( + return detail::visit&, ComponentsT...> ( std::forward (visitor), arg ); } + /// Call the invokable `VisitorT` with the value in the supplied tagged + /// union. template < typename VisitorT, template typename TaggedT, @@ -237,7 +224,7 @@ namespace cruft { { static_assert (sizeof...(ComponentsT)); - return detail::visit<0> ( + return detail::visit const&, ComponentsT...> ( std::forward (visitor), arg ); @@ -263,6 +250,7 @@ namespace cruft { ); } + template bool operator!= (tagged const &lhs, tagged const &rhs) {