some variant detail

main
Brett 2025-04-21 01:23:39 -04:00
parent e5a3c9d669
commit 606def7c10
3 changed files with 99 additions and 9 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
include(cmake/color.cmake)
set(BLT_VERSION 5.4.2)
set(BLT_VERSION 5.4.3)
set(BLT_TARGET BLT)

View File

@ -108,6 +108,15 @@ namespace blt
hell = (void*) &val;
(void) hell;
}
template<typename T>
BLT_ATTRIB_NO_INLINE T& black_box_ret(T& val)
{
static volatile void* hell;
hell = (void*) &val;
(void) hell;
return val;
}
template<typename T>
BLT_ATTRIB_NO_INLINE const T& black_box_ret(const T& val)

View File

@ -21,15 +21,98 @@
#include <functional>
#include <optional>
#include <stdexcept>
#include <type_traits>
#include <variant>
#include <blt/std/types.h>
#include "blt/logging/logging.h"
#include <tuple>
namespace blt
{
template <typename... Types>
class variant_t;
namespace detail
{
template <typename... Ts>
struct filter_void;
template <>
struct filter_void<>
{
using type = std::tuple<>;
};
template <typename T, typename... Ts>
struct filter_void<T, Ts...>
{
using type = std::conditional_t<
std::is_same_v<T, void>,
typename filter_void<Ts...>::type,
decltype(std::tuple_cat(
std::declval<std::tuple<T>>(),
std::declval<typename filter_void<Ts...>::type>()
))
>;
};
template <typename... Ts>
using filter_void_t = typename filter_void<Ts...>::type;
template <typename Type, typename... Args>
struct member_func_detail;
template <typename Type, typename First, typename... Rest>
struct member_func_detail<Type, First, Rest...>
{
template <typename Func>
using return_type = std::invoke_result_t<Func, Type>;
template <typename Func>
using can_invoke = std::is_invocable<Func, Type>;
template <typename Func>
using result_or_void = std::conditional<can_invoke<Func>::value, return_type<Func>, void>;
constexpr static bool all_has_void = std::conjunction_v<std::is_void<result_or_void<Rest>>...>;
using ret_type = std::conditional_t<all_has_void, void, decltype(std::get<0>(
std::declval<filter_void_t<return_type<First>, return_type<Rest>...>>()))>;
constexpr static bool all_has_ret = std::conjunction_v<std::is_same<ret_type, result_or_void<Rest>>...>;
constexpr static bool ret_or_void = std::conjunction_v<std::disjunction<
std::is_same<ret_type, result_or_void<Rest>>, std::is_void<result_or_void<Rest>>>...>;
template <size_t... Indexes>
static constexpr auto make_variant(std::index_sequence<Indexes...>)
{
if constexpr (all_has_void)
return;
using tuple_type = filter_void_t<First, Rest...>;
using variant = variant_t<decltype(std::get<Indexes>(std::declval<tuple_type>()))...>;
return std::declval<variant>();
}
using variant_type = decltype(make_variant(std::index_sequence_for<First, Rest...>{}));
static constexpr auto make_return_type()
{
if constexpr (all_has_void)
return;
if constexpr (all_has_ret)
return std::declval<ret_type>();
if constexpr (ret_or_void)
return std::declval<std::optional<ret_type>>();
return std::declval<variant_type>();
}
};
template <typename Type>
struct member_func_detail<Type>
{
};
}
/*
* std::visit(blt::lambda_visitor{
* lambdas...
@ -190,7 +273,7 @@ namespace blt
* @tparam should_throw Controls if the implementation should throw if the type stored in the variant doesn't have any matching member function
* @return Result of calling the member functions. All functions should return the same value, otherwise this won't compile.
*/
template <bool should_throw = false, typename... MemberFuncs>
template <typename... MemberFuncs>
constexpr auto call_member(const MemberFuncs... funcs)
{
static_assert(std::conjunction_v<std::is_member_function_pointer<std::decay_t<MemberFuncs>>...>,
@ -199,9 +282,8 @@ namespace blt
{
using ValueType = std::decay_t<decltype(value)>;
if constexpr (std::disjunction_v<std::is_invocable<std::decay_t<decltype(funcs)>, ValueType>...> && should_throw)
if constexpr (std::disjunction_v<std::is_invocable<std::decay_t<decltype(funcs)>, ValueType>...>)
{
throw std::runtime_error("No matching member function found");
}
return *(... || ([&](auto&& func) -> decltype(auto)
@ -222,8 +304,7 @@ namespace blt
{
return std::visit([=](auto&& value)
{
using ValueType = std::decay_t<decltype(value)>;
return ((value).*(cast_member_ptr<ValueType>(func)))(std::forward<Args>(args)...);
return ((value).*(func))(std::forward<Args>(args)...);
}, m_variant);
}