Source code

Revision control

Copy as Markdown

Other Tools

#pragma once
// IWYU pragma: private, include "rlbox.hpp"
// IWYU pragma: friend "rlbox_.*\.hpp"
#include <array>
#include <type_traits>
namespace rlbox::detail {
#define RLBOX_ENABLE_IF(...) std::enable_if_t<__VA_ARGS__>* = nullptr
template<typename T>
constexpr bool true_v = true;
template<typename T>
constexpr bool is_fundamental_or_enum_v =
std::is_fundamental_v<T> || std::is_enum_v<T>;
template<typename T>
constexpr bool is_basic_type_v =
std::is_fundamental_v<T> || std::is_enum_v<T> || std::is_pointer_v<T>;
template<typename T>
using valid_return_t =
std::conditional_t<std::is_function_v<T>, void*, std::decay_t<T>>;
template<typename T>
using valid_param_t = std::conditional_t<std::is_void_v<T>, void*, T>;
namespace func_first_arg_detail {
template<typename Ret, typename Arg, typename... Rest>
Arg func_first_arg_t_helper(Ret (*)(Arg, Rest...));
template<typename Ret, typename F, typename Arg, typename... Rest>
Arg func_first_arg_t_helper(Ret (F::*)(Arg, Rest...));
template<typename Ret, typename F, typename Arg, typename... Rest>
Arg func_first_arg_t_helper(Ret (F::*)(Arg, Rest...) const);
template<typename F>
decltype(func_first_arg_t_helper(&F::operator())) first_argument_helper(F);
}
template<typename T>
using func_first_arg_t =
decltype(func_first_arg_detail::first_argument_helper(std::declval<T>()));
namespace func_arg_nums_v_detail {
template<typename T_Ret, typename... T_Args>
constexpr size_t helper_two(T_Ret (*)(T_Args...))
{
return sizeof...(T_Args);
}
template<typename T_Func>
constexpr size_t helper()
{
constexpr T_Func* ptr = nullptr;
return helper_two(ptr);
}
}
template<typename T_Func>
constexpr size_t func_arg_nums_v = func_arg_nums_v_detail::helper<T_Func>();
template<typename T>
using valid_array_el_t =
std::conditional_t<std::is_void_v<T> || std::is_function_v<T>, int, T>;
template<typename T>
constexpr bool is_func_ptr_v = (std::is_pointer_v<T> &&
std::is_function_v<std::remove_pointer_t<T>>) ||
std::is_member_function_pointer_v<T>;
template<typename T>
constexpr bool is_func_or_func_ptr = std::is_function_v<T> || is_func_ptr_v<T>;
template<typename T>
constexpr bool is_one_level_ptr_v =
std::is_pointer_v<T> && !std::is_pointer_v<std::remove_pointer_t<T>>;
template<typename T_This, typename T_Target>
using add_const_if_this_const_t =
std::conditional_t<std::is_const_v<std::remove_pointer_t<T_This>>,
std::add_const_t<T_Target>,
T_Target>;
template<typename T>
using remove_const_from_pointer = std::conditional_t<
std::is_pointer_v<T>,
std::add_pointer_t<std::remove_const_t<std::remove_pointer_t<T>>>,
T>;
template<typename T>
using add_const_from_pointer = std::conditional_t<
std::is_pointer_v<T>,
std::remove_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>,
T>;
template<typename T>
using remove_cv_ref_t = std::remove_cv_t<std::remove_reference_t<T>>;
template<typename T>
using c_to_std_array_t =
std::conditional_t<std::is_array_v<T>,
std::array<std::remove_extent_t<T>, std::extent_v<T>>,
T>;
namespace std_array_to_c_arr_detail {
template<typename T>
struct W
{
using type = T;
};
template<typename T, size_t N>
W<T[N]> std_array_to_c_arr_helper(std::array<T, N>);
template<typename T>
W<T> std_array_to_c_arr_helper(T&&);
}
template<typename T>
using std_array_to_c_arr_t =
typename decltype(std_array_to_c_arr_detail::std_array_to_c_arr_helper(
std::declval<T>()))::type;
template<typename T>
using dereference_result_t =
std::conditional_t<std::is_pointer_v<T>,
std::remove_pointer_t<T>,
std::remove_extent_t<std_array_to_c_arr_t<T>> // is_array
>;
template<typename T>
using value_type_t =
std::conditional_t<std::is_array_v<T>, c_to_std_array_t<T>, T>;
template<typename T>
using function_ptr_t =
std::conditional_t<std::is_pointer_v<T> &&
std::is_function_v<std::remove_pointer_t<T>>,
T,
int (*)(int)>;
namespace is_c_or_std_array_detail {
template<typename T, typename T_Enable = void>
struct is_c_or_std_array_helper;
template<typename T>
struct is_c_or_std_array_helper<T, std::enable_if_t<std::is_array_v<T>>>
: std::true_type
{};
template<typename T, size_t N>
std::true_type is_std_array_helper(std::array<T, N>*);
template<typename T>
std::false_type is_std_array_helper(T*);
template<typename T>
constexpr bool is_std_array_v =
decltype(is_std_array_helper(std::declval<std::add_pointer_t<T>>()))::value;
template<typename T>
struct is_c_or_std_array_helper<T, std::enable_if_t<is_std_array_v<T>>>
: std::true_type
{};
template<typename T>
struct is_c_or_std_array_helper<
T,
std::enable_if_t<!std::is_array_v<T> && !is_std_array_v<T>>>
: std::false_type
{};
}
template<typename T>
constexpr bool is_std_array_v = is_c_or_std_array_detail::is_std_array_v<T>;
template<typename T>
constexpr bool is_c_or_std_array_v =
is_c_or_std_array_detail::is_c_or_std_array_helper<T>::value;
namespace std_array_el_detail {
template<typename T>
struct W
{
using type = T;
};
template<typename T, size_t N>
W<T> is_std_array_helper(std::array<T, N>*);
template<typename T>
W<void> is_std_array_helper(T*);
template<typename T>
using std_array_el_t = decltype(std_array_el_detail::is_std_array_helper(
std::declval<std::add_pointer_t<T>>));
}
template<typename T>
using std_array_el_t = typename std_array_el_detail::std_array_el_t<T>::type;
namespace all_extents_same_detail {
template<typename T1, typename T2, typename T_Enable = void>
struct all_extents_same_helper;
template<typename T1, typename T2>
struct all_extents_same_helper<
T1,
T2,
std::enable_if_t<std::rank_v<T1> != std::rank_v<T2>>> : std::false_type
{};
template<typename T1, typename T2>
struct all_extents_same_helper<
T1,
T2,
std::enable_if_t<std::rank_v<T1> == std::rank_v<T2> &&
!std::is_array_v<T1> && !std::is_array_v<T2>>>
: std::true_type
{};
template<typename T1, typename T2>
struct all_extents_same_helper<
T1,
T2,
std::enable_if_t<std::rank_v<T1> == std::rank_v<T2> &&
std::is_array_v<T1> && std::is_array_v<T2> &&
std::extent_v<T1> != std::extent_v<T2>>> : std::false_type
{};
template<typename T1, typename T2>
struct all_extents_same_helper<
T1,
T2,
std::enable_if_t<std::rank_v<T1> == std::rank_v<T2> &&
std::is_array_v<T1> && std::is_array_v<T2> &&
std::extent_v<T1> == std::extent_v<T2>>>
{
static constexpr bool value =
all_extents_same_helper<std::remove_extent_t<T1>,
std::remove_extent_t<T2>>::value;
};
}
template<typename T1, typename T2>
constexpr bool all_extents_same =
all_extents_same_detail::all_extents_same_helper<T1, T2>::value;
// remove all pointers/extent types
namespace remove_all_pointers_detail {
template<typename T>
struct remove_all_pointers
{
typedef T type;
};
template<typename T>
struct remove_all_pointers<T*>
{
typedef typename remove_all_pointers<T>::type type;
};
}
template<typename T>
using remove_all_pointers_t =
typename remove_all_pointers_detail::remove_all_pointers<T>::type;
// remove all pointers/extent types
namespace base_type_detail {
template<typename T>
struct base_type
{
typedef T type;
};
template<typename T>
struct base_type<T*>
{
typedef typename base_type<T>::type type;
};
template<typename T>
struct base_type<T[]>
{
typedef typename base_type<T>::type type;
};
template<typename T, std::size_t N>
struct base_type<T[N]>
{
typedef typename base_type<T>::type type;
};
}
template<typename T>
using base_type_t = typename base_type_detail::base_type<T>::type;
// convert types
namespace convert_detail {
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType,
typename T_Enable = void>
struct convert_base_types_t_helper;
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
struct convert_base_types_t_helper<
T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType,
std::enable_if_t<std::is_same_v<short, T> && !std::is_const_v<T>>>
{
using type = T_ShortType;
};
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
struct convert_base_types_t_helper<
T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType,
std::enable_if_t<std::is_same_v<int, T> && !std::is_const_v<T>>>
{
using type = T_IntType;
};
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
struct convert_base_types_t_helper<
T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType,
std::enable_if_t<std::is_same_v<long, T> && !std::is_const_v<T>>>
{
using type = T_LongType;
};
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
struct convert_base_types_t_helper<
T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType,
std::enable_if_t<std::is_same_v<long long, T> && !std::is_const_v<T>>>
{
using type = T_LongLongType;
};
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
struct convert_base_types_t_helper<
T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType,
std::enable_if_t<std::is_pointer_v<T> && !std::is_const_v<T>>>
{
using type = T_PointerType;
};
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
struct convert_base_types_t_helper<
T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType,
std::enable_if_t<std::is_unsigned_v<T> && !std::is_same_v<T, bool> &&
!std::is_same_v<T, char> && !std::is_const_v<T> &&
!std::is_enum_v<T>>>
{
using type = std::make_unsigned_t<
typename convert_base_types_t_helper<std::make_signed_t<T>,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType>::type>;
};
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
struct convert_base_types_t_helper<
T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType,
std::enable_if_t<(
std::is_same_v<bool, T> || std::is_same_v<void, T> ||
std::is_same_v<char, T> || std::is_same_v<signed char, T> ||
std::is_floating_point_v<T> || std::is_enum_v<T>)&&!std::is_const_v<T>>>
{
using type = T;
};
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
struct convert_base_types_t_helper<
T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType,
std::enable_if_t<std::is_array_v<T> && !std::is_const_v<T>>>
{
using type = typename convert_base_types_t_helper<
std::remove_extent_t<T>,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType>::type[std::extent_v<T>];
};
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
struct convert_base_types_t_helper<T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType,
std::enable_if_t<std::is_const_v<T>>>
{
using type = std::add_const_t<
typename convert_base_types_t_helper<std::remove_const_t<T>,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType>::type>;
};
}
template<typename T,
typename T_ShortType,
typename T_IntType,
typename T_LongType,
typename T_LongLongType,
typename T_PointerType>
using convert_base_types_t =
typename convert_detail::convert_base_types_t_helper<T,
T_ShortType,
T_IntType,
T_LongType,
T_LongLongType,
T_PointerType>::type;
namespace unsigned_int_of_size_t_detail {
template<typename T, typename T_Enable = void>
struct unsigned_int_of_size_t_helper;
template<typename T>
struct unsigned_int_of_size_t_helper<T, std::enable_if_t<sizeof(T) == 1>>
{
using type = uint8_t;
};
template<typename T>
struct unsigned_int_of_size_t_helper<T, std::enable_if_t<sizeof(T) == 2>>
{
using type = uint16_t;
};
template<typename T>
struct unsigned_int_of_size_t_helper<T, std::enable_if_t<sizeof(T) == 4>>
{
using type = uint32_t;
};
template<typename T>
struct unsigned_int_of_size_t_helper<T, std::enable_if_t<sizeof(T) == 8>>
{
using type = uint64_t;
};
}
template<typename T>
using unsigned_int_of_size_t =
typename unsigned_int_of_size_t_detail::unsigned_int_of_size_t_helper<
T>::type;
}