From 2d6d924d664db4e7c526a9a08ff5cc948e017bba Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Tue, 22 Sep 2020 07:53:58 +1000 Subject: [PATCH] types/tagged: support cvref in `visit` --- types/tagged.hpp | 63 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/types/tagged.hpp b/types/tagged.hpp index f85a19f6..716003da 100644 --- a/types/tagged.hpp +++ b/types/tagged.hpp @@ -14,6 +14,8 @@ #include "../maths.hpp" #include "../tuple/type.hpp" +#include + /////////////////////////////////////////////////////////////////////////////// namespace cruft { @@ -64,6 +66,7 @@ namespace cruft { tagged (tagged &&) = default; tagged& operator= (tagged const&) = default; + tagged& operator= (tagged &) = default; tagged& operator= (tagged &&) = default; @@ -134,8 +137,30 @@ namespace cruft { cruft::max (sizeof (ValueT)...) ]; }; +} +namespace std { + template + struct tuple_size<::cruft::tagged> + : std::integral_constant<::std::size_t, sizeof...(ComponentT)> + { ; }; + + + template + struct tuple_element< + I, + ::cruft::tagged + > + : ::std::tuple_element< + I, + std::tuple + > + { ; }; +} + + +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 @@ -146,25 +171,20 @@ namespace cruft { template < std::size_t IndexV, typename VisitorT, - template typename TaggedT, - typename ...ComponentsT - > - requires std::is_same_v< - std::remove_cvref_t>, - tagged + typename TaggedT > decltype (auto) visit ( VisitorT &&visitor, - TaggedT arg + TaggedT &&arg ) { - static_assert (IndexV < sizeof...(ComponentsT)); - using nth_t = std::tuple_element_t>; + 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 == sizeof...(ComponentsT)) { + if constexpr (IndexV + 1 == std::tuple_size_v>) { return std::invoke (visitor, arg.template get ()); } else { // If the tag matches, then dispatch, else recurse with the @@ -192,7 +212,28 @@ namespace cruft { tagged > decltype (auto) - visit (VisitorT &&visitor, TaggedT arg) + visit (VisitorT &&visitor, TaggedT &arg) + { + static_assert (sizeof...(ComponentsT)); + + return detail::visit<0> ( + std::forward (visitor), + arg + ); + } + + + template < + typename VisitorT, + template typename TaggedT, + typename ...ComponentsT + > + requires std::is_same_v< + std::remove_cvref_t>, + tagged + > + decltype (auto) + visit (VisitorT &&visitor, TaggedT const &arg) { static_assert (sizeof...(ComponentsT));