mijin2/source/mijin/util/traits.hpp

164 lines
4.5 KiB
C++

#pragma once
#if !defined(MIJIN_UTIL_TRAITS_HPP_INCLUDED)
#define MIJIN_UTIL_TRAITS_HPP_INCLUDED 1
#include <tuple>
namespace mijin
{
//
// public defines
//
//
// public constants
//
//
// public types
//
template<typename T>
struct always_false
{
static constexpr bool value = false;
};
template<typename T>
inline constexpr bool always_false_v = always_false<T>::value;
template<auto V>
struct always_false_val
{
static constexpr bool value = false;
};
template<auto V>
inline constexpr bool always_false_val_v = always_false_val<V>::value;
template<template<typename> typename TFilter, typename... TArgs>
struct TypeFilter;
template<template<typename> typename TFilter>
struct TypeFilter<TFilter>
{
using type_t = std::tuple<>;
};
template<template<typename> typename TFilter, typename TFirst, typename... TArgs>
struct TypeFilter<TFilter, TFirst, TArgs...>
{
static consteval auto makeTypeHelper()
{
using base_t = typename TypeFilter<TFilter, TArgs...>::type_t;
// note: not using decltype, as the compiler might think it is being evaluated
if constexpr (!TFilter<TFirst>::value) {
return static_cast<base_t*>(nullptr);
}
else {
auto wrapper = []<typename... TArgsInner>(std::tuple<TArgsInner...>*)
{
return static_cast<std::tuple<TFirst, TArgsInner...>*>(nullptr);
};
return wrapper(static_cast<base_t*>(nullptr));
}
}
using type_t = std::remove_pointer_t<decltype(makeTypeHelper())>;
};
template<template<typename> typename TFilter, typename... TArgs>
auto typeFilterHelper(std::tuple<TArgs...>*)
{
return static_cast<typename TypeFilter<TFilter, TArgs...>::type_t*>(nullptr);
}
template<template<typename> typename TFilter, typename TTuple>
using filter_types_t = std::remove_pointer_t<decltype(typeFilterHelper<TFilter>(static_cast<TTuple*>(nullptr)))>;
template<template<typename> typename TPredicate, typename... TArgs>
auto mapTypesHelper(std::tuple<TArgs...>)
{
return static_cast<std::tuple<TPredicate<TArgs>...>*>(nullptr);
}
template<template<typename> typename TPredicate, typename TTuple>
using map_types_t = std::remove_pointer_t<decltype(mapTypesHelper<TPredicate>(std::declval<TTuple>()))>;
template<template<typename> typename TPredicate, template<typename> typename TTemplate>
struct map_template {
template<typename T>
using type_t = TTemplate<TPredicate<T>>;
};
template<typename T, typename... Types>
struct is_any_type : std::disjunction<std::is_same<T, Types>...> {};
template<typename T, typename... Types>
static constexpr bool is_any_type_v = is_any_type<T, Types...>::value;
template<typename TElement, typename TCollection>
struct is_type_member;
template<typename TElement, template<typename...> typename TCollection, typename... Ts>
struct is_type_member<TElement, TCollection<Ts...>>
: std::bool_constant<(... || std::is_same<TElement, Ts>{})>
{};
template<typename TElement, typename TCollection>
constexpr bool is_type_member_v = is_type_member<TElement, TCollection>::value;
template<typename TFrom, typename TTo>
using copy_const_t = std::conditional_t<std::is_const_v<TFrom>, std::add_const_t<TTo>, std::remove_const_t<TTo>>;
template<typename TFrom, typename TTo>
using copy_volatile_t = std::conditional_t<std::is_volatile_v<TFrom>, std::add_volatile_t<TTo>, std::remove_volatile_t<TTo>>;
template<typename TFrom, typename TTo>
using copy_cv_t = copy_const_t<TFrom, copy_volatile_t<TFrom, TTo>>;
template<typename TActual, typename TDelay>
using delay_type_t = TActual;
template<std::size_t I, typename TArg, typename... TArgs>
struct TypeAtHelper
{
using type_t = typename TypeAtHelper<I-1, TArgs...>::type_t;
};
template<typename TArg, typename... TArgs>
struct TypeAtHelper<0, TArg, TArgs...>
{
using type_t = TArg;
};
template<std::size_t I, typename... TArgs>
using type_at_t = TypeAtHelper<I, TArgs...>::type_t;
template<template<typename...> typename TTemplate, typename TType>
struct is_template_instance : std::false_type {};
template<template<typename...> typename TTemplate, typename... TArgs>
struct is_template_instance<TTemplate, TTemplate<TArgs...>> : std::true_type {};
template<template<typename...> typename TTemplate, typename TType>
constexpr bool is_template_instance_v = is_template_instance<TTemplate, TType>::value;
//
// public functions
//
template<typename THelper, typename TType>
decltype(auto) delayEvaluation(TType&& value)
{
return static_cast<TType&&>(value);
}
} // namespace mijin
#endif // !defined(MIJIN_UTIL_TRAITS_HPP_INCLUDED)