types/tagged: support cvref in visit
This commit is contained in:
parent
a392ca1aa9
commit
2d6d924d66
@ -14,6 +14,8 @@
|
|||||||
#include "../maths.hpp"
|
#include "../maths.hpp"
|
||||||
#include "../tuple/type.hpp"
|
#include "../tuple/type.hpp"
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
namespace cruft {
|
namespace cruft {
|
||||||
@ -64,6 +66,7 @@ namespace cruft {
|
|||||||
tagged (tagged &&) = default;
|
tagged (tagged &&) = default;
|
||||||
|
|
||||||
tagged& operator= (tagged const&) = default;
|
tagged& operator= (tagged const&) = default;
|
||||||
|
tagged& operator= (tagged &) = default;
|
||||||
tagged& operator= (tagged &&) = default;
|
tagged& operator= (tagged &&) = default;
|
||||||
|
|
||||||
|
|
||||||
@ -134,8 +137,30 @@ namespace cruft {
|
|||||||
cruft::max (sizeof (ValueT)...)
|
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 {
|
namespace detail {
|
||||||
// If the tagged object matches the IndexV'th type in ComponentsT then
|
// If the tagged object matches the IndexV'th type in ComponentsT then
|
||||||
// invoke visitor with the object as the argument. Else, advance to
|
// invoke visitor with the object as the argument. Else, advance to
|
||||||
@ -146,25 +171,20 @@ namespace cruft {
|
|||||||
template <
|
template <
|
||||||
std::size_t IndexV,
|
std::size_t IndexV,
|
||||||
typename VisitorT,
|
typename VisitorT,
|
||||||
template <typename...> typename TaggedT,
|
typename TaggedT
|
||||||
typename ...ComponentsT
|
|
||||||
>
|
|
||||||
requires std::is_same_v<
|
|
||||||
std::remove_cvref_t<TaggedT<ComponentsT...>>,
|
|
||||||
tagged<ComponentsT...>
|
|
||||||
>
|
>
|
||||||
decltype (auto)
|
decltype (auto)
|
||||||
visit (
|
visit (
|
||||||
VisitorT &&visitor,
|
VisitorT &&visitor,
|
||||||
TaggedT<ComponentsT...> arg
|
TaggedT &&arg
|
||||||
) {
|
) {
|
||||||
static_assert (IndexV < sizeof...(ComponentsT));
|
static_assert (IndexV < std::tuple_size_v<std::remove_cvref_t<TaggedT>>);
|
||||||
using nth_t = std::tuple_element_t<IndexV, std::tuple<ComponentsT...>>;
|
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
|
// If we're the last valid index then we must be invoked because
|
||||||
// there's no other option. Do this, and (statically) avoid
|
// there's no other option. Do this, and (statically) avoid
|
||||||
// further recursion.
|
// 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> ());
|
return std::invoke (visitor, arg.template get<nth_t> ());
|
||||||
} else {
|
} else {
|
||||||
// If the tag matches, then dispatch, else recurse with the
|
// If the tag matches, then dispatch, else recurse with the
|
||||||
@ -192,7 +212,28 @@ namespace cruft {
|
|||||||
tagged<ComponentsT...>
|
tagged<ComponentsT...>
|
||||||
>
|
>
|
||||||
decltype (auto)
|
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));
|
static_assert (sizeof...(ComponentsT));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user