types/tagged: support cvref in visit
This commit is contained in:
parent
a392ca1aa9
commit
2d6d924d66
@ -14,6 +14,8 @@
|
||||
#include "../maths.hpp"
|
||||
#include "../tuple/type.hpp"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
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 <typename ...ComponentT>
|
||||
struct tuple_size<::cruft::tagged<ComponentT...>>
|
||||
: std::integral_constant<::std::size_t, sizeof...(ComponentT)>
|
||||
{ ; };
|
||||
|
||||
|
||||
template <std::size_t I, typename ...ComponentT>
|
||||
struct tuple_element<
|
||||
I,
|
||||
::cruft::tagged<ComponentT...>
|
||||
>
|
||||
: ::std::tuple_element<
|
||||
I,
|
||||
std::tuple<ComponentT...>
|
||||
>
|
||||
{ ; };
|
||||
}
|
||||
|
||||
|
||||
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...> typename TaggedT,
|
||||
typename ...ComponentsT
|
||||
>
|
||||
requires std::is_same_v<
|
||||
std::remove_cvref_t<TaggedT<ComponentsT...>>,
|
||||
tagged<ComponentsT...>
|
||||
typename TaggedT
|
||||
>
|
||||
decltype (auto)
|
||||
visit (
|
||||
VisitorT &&visitor,
|
||||
TaggedT<ComponentsT...> arg
|
||||
TaggedT &&arg
|
||||
) {
|
||||
static_assert (IndexV < sizeof...(ComponentsT));
|
||||
using nth_t = std::tuple_element_t<IndexV, std::tuple<ComponentsT...>>;
|
||||
static_assert (IndexV < std::tuple_size_v<std::remove_cvref_t<TaggedT>>);
|
||||
using nth_t = std::tuple_element_t<IndexV, std::remove_reference_t<TaggedT>>;
|
||||
|
||||
// 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<std::remove_reference_t<TaggedT>>) {
|
||||
return std::invoke (visitor, arg.template get<nth_t> ());
|
||||
} else {
|
||||
// If the tag matches, then dispatch, else recurse with the
|
||||
@ -192,7 +212,28 @@ namespace cruft {
|
||||
tagged<ComponentsT...>
|
||||
>
|
||||
decltype (auto)
|
||||
visit (VisitorT &&visitor, TaggedT<ComponentsT...> arg)
|
||||
visit (VisitorT &&visitor, TaggedT<ComponentsT...> &arg)
|
||||
{
|
||||
static_assert (sizeof...(ComponentsT));
|
||||
|
||||
return detail::visit<0> (
|
||||
std::forward<VisitorT> (visitor),
|
||||
arg
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template <
|
||||
typename VisitorT,
|
||||
template <typename...> typename TaggedT,
|
||||
typename ...ComponentsT
|
||||
>
|
||||
requires std::is_same_v<
|
||||
std::remove_cvref_t<TaggedT<ComponentsT...>>,
|
||||
tagged<ComponentsT...>
|
||||
>
|
||||
decltype (auto)
|
||||
visit (VisitorT &&visitor, TaggedT<ComponentsT...> const &arg)
|
||||
{
|
||||
static_assert (sizeof...(ComponentsT));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user