|
|
|
@ -9,7 +9,7 @@
|
|
|
|
|
#include <type_traits>
|
|
|
|
|
#include <functional>
|
|
|
|
|
#include "../serialize.h"
|
|
|
|
|
#include "../invoke.h"
|
|
|
|
|
#include "../utility.h"
|
|
|
|
|
|
|
|
|
|
namespace dlib
|
|
|
|
|
{
|
|
|
|
@ -139,41 +139,38 @@ namespace dlib
|
|
|
|
|
typename std::aligned_union<0, Types...>::type mem;
|
|
|
|
|
int type_identity = 0;
|
|
|
|
|
|
|
|
|
|
template<
|
|
|
|
|
typename F,
|
|
|
|
|
typename TSU,
|
|
|
|
|
std::size_t I
|
|
|
|
|
>
|
|
|
|
|
static void apply_to_contents_as_type(
|
|
|
|
|
F&& f,
|
|
|
|
|
TSU&& me
|
|
|
|
|
)
|
|
|
|
|
template<typename F, typename TSU>
|
|
|
|
|
struct dispatcher
|
|
|
|
|
{
|
|
|
|
|
std::forward<F>(f)(me.template unchecked_get<get_type_t<I>>());
|
|
|
|
|
}
|
|
|
|
|
constexpr static const std::size_t N = sizeof...(Types);
|
|
|
|
|
using R = decltype(std::declval<F>()(std::declval<TSU>().template unchecked_get<get_type_t<0>>()));
|
|
|
|
|
|
|
|
|
|
template<
|
|
|
|
|
typename F,
|
|
|
|
|
typename TSU,
|
|
|
|
|
std::size_t... I
|
|
|
|
|
>
|
|
|
|
|
static void apply_to_contents_impl(
|
|
|
|
|
F&& f,
|
|
|
|
|
TSU&& me,
|
|
|
|
|
dlib::index_sequence<I...>
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
using func_t = void(*)(F&&, TSU&&);
|
|
|
|
|
constexpr static const bool is_noexcept =
|
|
|
|
|
And<std::is_default_constructible<R>::value &&
|
|
|
|
|
noexcept(std::declval<F>()(std::declval<TSU>().template unchecked_get<Types>()))...>::value;
|
|
|
|
|
|
|
|
|
|
const func_t vtable[] = {
|
|
|
|
|
/*! Empty (type_identity == 0) case !*/
|
|
|
|
|
[](F&&, TSU&&) {
|
|
|
|
|
},
|
|
|
|
|
/*! Non-empty cases !*/
|
|
|
|
|
&apply_to_contents_as_type<F&&,TSU&&,I>...
|
|
|
|
|
};
|
|
|
|
|
template<size_t I, typename std::enable_if<I == N, bool>::type = true>
|
|
|
|
|
inline R operator()(F&&, TSU&&, size_<I>)
|
|
|
|
|
noexcept(is_noexcept) { return R(); }
|
|
|
|
|
|
|
|
|
|
template<size_t I, typename std::enable_if<I < N, bool>::type = true>
|
|
|
|
|
inline R operator()(F&& f, TSU&& me, size_<I>)
|
|
|
|
|
noexcept(is_noexcept)
|
|
|
|
|
{
|
|
|
|
|
if (me.is_empty())
|
|
|
|
|
return R();
|
|
|
|
|
else if (me.get_current_type_id() == (I+1))
|
|
|
|
|
return std::forward<F>(f)(me.template unchecked_get<get_type_t<I>>());
|
|
|
|
|
else
|
|
|
|
|
return (*this)(std::forward<F>(f), std::forward<TSU>(me), size_<I+1>{});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return vtable[me.get_current_type_id()](std::forward<F>(f), std::forward<TSU>(me));
|
|
|
|
|
template<typename F, typename TSU>
|
|
|
|
|
static inline auto dispatch(F&& f, TSU&& me)
|
|
|
|
|
noexcept(noexcept(dispatcher<F&&,TSU&&>{}(std::forward<F>(f), std::forward<TSU>(me), size_<0>{})))
|
|
|
|
|
-> decltype(dispatcher<F&&,TSU&&>{}(std::forward<F>(f), std::forward<TSU>(me), size_<0>{})) {
|
|
|
|
|
return dispatcher<F&&,TSU&&>{}(std::forward<F>(f), std::forward<TSU>(me), size_<0>{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
@ -402,19 +399,19 @@ namespace dlib
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
void apply_to_contents(
|
|
|
|
|
auto apply_to_contents(
|
|
|
|
|
F&& f
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
apply_to_contents_impl(std::forward<F>(f), *this, dlib::make_index_sequence<sizeof...(Types)>{});
|
|
|
|
|
) noexcept(noexcept(dispatch(std::forward<F>(f), std::declval<type_safe_union&>())))
|
|
|
|
|
-> decltype(dispatch(std::forward<F>(f), *this)) {
|
|
|
|
|
return dispatch(std::forward<F>(f), *this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
void apply_to_contents(
|
|
|
|
|
auto apply_to_contents(
|
|
|
|
|
F&& f
|
|
|
|
|
) const
|
|
|
|
|
{
|
|
|
|
|
apply_to_contents_impl(std::forward<F>(f), *this, dlib::make_index_sequence<sizeof...(Types)>{});
|
|
|
|
|
) const noexcept(noexcept(dispatch(std::forward<F>(f), std::declval<const type_safe_union&>())))
|
|
|
|
|
-> decltype(dispatch(std::forward<F>(f), *this)) {
|
|
|
|
|
return dispatch(std::forward<F>(f), *this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
@ -492,7 +489,7 @@ namespace dlib
|
|
|
|
|
{
|
|
|
|
|
if (type_identity == item.type_identity)
|
|
|
|
|
{
|
|
|
|
|
item.apply_to_contents(swap_to{*this});
|
|
|
|
|
apply_to_contents(swap_to{item});
|
|
|
|
|
}
|
|
|
|
|
else if (is_empty())
|
|
|
|
|
{
|
|
|
|
@ -540,48 +537,6 @@ namespace dlib
|
|
|
|
|
)...
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<
|
|
|
|
|
typename R,
|
|
|
|
|
typename F,
|
|
|
|
|
typename TSU,
|
|
|
|
|
std::size_t I
|
|
|
|
|
>
|
|
|
|
|
R visit_impl_as_type(
|
|
|
|
|
F&& f,
|
|
|
|
|
TSU&& tsu
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
using Tsu = typename std::decay<TSU>::type;
|
|
|
|
|
using T = type_safe_union_alternative_t<I, Tsu>;
|
|
|
|
|
return dlib::invoke(std::forward<F>(f), tsu.template cast_to<T>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<
|
|
|
|
|
typename R,
|
|
|
|
|
typename F,
|
|
|
|
|
typename TSU,
|
|
|
|
|
std::size_t... I
|
|
|
|
|
>
|
|
|
|
|
R visit_impl(
|
|
|
|
|
F&& f,
|
|
|
|
|
TSU&& tsu,
|
|
|
|
|
dlib::index_sequence<I...>
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
using func_t = R(*)(F&&, TSU&&);
|
|
|
|
|
|
|
|
|
|
const func_t vtable[] = {
|
|
|
|
|
/*! Empty (type_identity == 0) case !*/
|
|
|
|
|
[](F&&, TSU&&) {
|
|
|
|
|
return R();
|
|
|
|
|
},
|
|
|
|
|
/*! Non-empty cases !*/
|
|
|
|
|
&visit_impl_as_type<R,F&&,TSU&&,I>...
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return vtable[tsu.get_current_type_id()](std::forward<F>(f), std::forward<TSU>(tsu));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<
|
|
|
|
@ -598,20 +553,13 @@ namespace dlib
|
|
|
|
|
detail::for_each_type_impl(std::forward<F>(f), std::forward<TSU>(tsu), dlib::make_index_sequence<Size>{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<
|
|
|
|
|
typename F,
|
|
|
|
|
typename TSU,
|
|
|
|
|
typename Tsu = typename std::decay<TSU>::type,
|
|
|
|
|
typename T0 = type_safe_union_alternative_t<0, Tsu>
|
|
|
|
|
>
|
|
|
|
|
template<typename F, typename TSU>
|
|
|
|
|
auto visit(
|
|
|
|
|
F&& f,
|
|
|
|
|
TSU&& tsu
|
|
|
|
|
) -> dlib::invoke_result_t<F, decltype(tsu.template cast_to<T0>())>
|
|
|
|
|
{
|
|
|
|
|
using ReturnType = dlib::invoke_result_t<F, decltype(tsu.template cast_to<T0>())>;
|
|
|
|
|
static constexpr std::size_t Size = type_safe_union_size<Tsu>::value;
|
|
|
|
|
return detail::visit_impl<ReturnType>(std::forward<F>(f), std::forward<TSU>(tsu), dlib::make_index_sequence<Size>{});
|
|
|
|
|
) noexcept(noexcept(tsu.apply_to_contents(std::forward<F>(f))))
|
|
|
|
|
-> decltype(tsu.apply_to_contents(std::forward<F>(f))) {
|
|
|
|
|
return tsu.apply_to_contents(std::forward<F>(f));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace detail
|
|
|
|
|