|
|
- #pragma once
-
- #include <type_traits>
- #include <typeinfo>
- #include <cstddef>
- #include <limits>
- #include "gp/algorithm/min_max.hpp"
-
-
- namespace gp{
- /**
- * @brief Picks either of the types depending on the condition
- *
- * @tparam cond the condition
- * @tparam T the type picked when the condition is true
- * @tparam U the type picked when the condition is false
- */
- template<bool cond, typename T, typename U>
- struct either
- {
- };
-
- template<typename T, typename U>
- struct either<true,T,U>
- {
- typedef T type;
- };
-
- template<typename T, typename U>
- struct either<false,T,U>
- {
- typedef U type;
- };
-
- /**
- * @brief Checks if the provided booleans are all true at compile time
- */
- template<bool first, bool ...list>
- struct constexpr_all_of
- {
- static constexpr bool value = first && constexpr_all_of<list...>::value;
- };
-
- template<bool first>
- struct constexpr_all_of<first>
- {
- static constexpr bool value = first;
- };
-
- /**
- * @brief Checks if at least one of the provided booleans is true at compile time
- */
- template<bool first, bool ...list>
- struct constexpr_any_of
- {
- static constexpr bool value = first || constexpr_any_of<list...>::value;
- };
-
- template<bool first>
- struct constexpr_any_of<first>
- {
- static constexpr bool value = first;
- };
-
- /**
- * @brief Checks if the provided type has a compile time defined size
- *
- * @tparam T the tested type
- * @return true if it has a defined size
- * @return false if its size may change due to inheritance or other factors
- */
- template<typename T>
- constexpr bool is_fixed_size()
- {
- return std::is_final<T>::value
- || std::is_fundamental<T>::value;
- }
-
- /**
- * @brief Checks if the provided typelist is all of fixed size
- */
- template<typename T, typename ...rest>
- struct all_of_fixed_size
- {
- static constexpr bool value = is_fixed_size<T>() && all_of_fixed_size<rest...>::value;
- };
-
- template<typename T>
- struct all_of_fixed_size<T>
- {
- static constexpr bool value = is_fixed_size<T>();
- };
-
- /**
- * @brief Checks if the provided list contains the provided class
- *
- * @tparam Univ the class to look for
- */
- template<typename Univ, typename T, typename ...rest>
- struct list_contains_class
- {
- static constexpr bool value = (
- std::is_same<T, Univ>::value
- ) || list_contains_class<Univ, rest...>::value;
- };
-
- template<typename Univ, typename T>
- struct list_contains_class<Univ, T>
- {
- static constexpr bool value = std::is_same<T, Univ>::value;
- };
-
- /**
- * @brief gives the index of Univ from the end of the argument list
- *
- * @tparam Univ The type to look for
- */
- template<typename Univ, typename T, typename ...rest>
- struct r_index_of
- {
- static constexpr std::size_t value = std::is_same<T, Univ>::value ? sizeof...(rest) : r_index_of<Univ, rest...>::value;
- };
-
- template<typename Univ, typename T>
- struct r_index_of<Univ, T>
- {
- static constexpr std::size_t value = std::is_same<T, Univ>::value ? 0 : std::numeric_limits<std::size_t>::max();
- };
-
-
- /**
- * @brief gives the type of the idx value from the end of the argument list
- *
- * @tparam idx The index to return the type of
- */
- template<size_t idx, typename T, typename ...rest>
- struct r_index_at
- {
- using type =
- typename either<
- idx==sizeof...(rest),
- T,
- typename r_index_at<idx,rest...>::type
- >::type;
- };
-
- /**
- * @brief extracts the first type of the list
- */
- template<typename U, typename ...rest>
- struct first_of {
- using type = U;
- };
-
- /**
- * @brief gives the size of the largest element in the provided list
- *
- * @return constexpr std::size_t equal to the largest size of all
- */
- template<typename T, typename U, typename ...rest>
- constexpr std::size_t max_size()
- {
- if constexpr (sizeof...(rest) == 0)
- {
- return gp::max(sizeof(T),sizeof(U));
- }
- else
- {
- return max_size<
- typename either<
- ( sizeof(T) > sizeof(U) ),
- T,
- U
- >::type,
- rest...>();
- }
- }
-
- /**
- * @brief remove reference state from the provided type
- */
- template<typename T>
- struct remove_reference
- {
- using type = T;
- };
-
- template<typename T>
- struct remove_reference<T&>
- {
- using type = T;
- };
-
- template<typename T>
- struct remove_reference<T&&>
- {
- using type = T;
- };
-
- /**
- * @brief Has a value of true if the provided type has a size() function member
- */
- template<typename T>
- struct has_size_interface
- {
- private:
- typedef std::true_type yes;
- typedef std::false_type no;
-
- template<typename U, size_t (U::*f)() const> struct SFINAE{};
-
-
- template<class C> static yes test(SFINAE<C,&C::size>*);
- template<class C> static no test(...);
-
- public:
- static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
- };
-
- /**
- * @brief Has a value of true if the provided type has a begin() function member
- */
- template<typename T>
- struct has_begin_interface
- {
- private:
- typedef std::true_type yes;
- typedef std::false_type no;
-
- template<typename U, auto (U::*f)() const> struct SFINAE{};
-
-
- template<class C> static yes test(SFINAE<C,&C::begin>*);
- template<class C> static no test(...);
-
- public:
- static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
- };
-
- /**
- * @brief Has a value of true if the provided type has a end() function member
- */
- template<typename T>
- struct has_end_interface
- {
- private:
- typedef std::true_type yes;
- typedef std::false_type no;
-
- template<typename U, auto (U::*f)() const> struct SFINAE{};
-
-
- template<class C> static yes test(SFINAE<C,&C::end>*);
- template<class C> static no test(...);
-
- public:
- static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
- };
-
- // TODO: Replace those with concepts
-
- template<typename T>
- using has_range_interface = constexpr_all_of<has_begin_interface<T>::value,has_end_interface<T>::value>;
-
- template<typename T>
- using has_measurable_range_interface = constexpr_all_of<has_range_interface<T>::value,has_size_interface<T>::value>;
-
-
-
- template<typename T>
- struct has_allocate_interface
- {
- private:
- typedef std::true_type yes;
- typedef std::false_type no;
-
- template<typename U, void* (U::*f)(size_t)> struct SFINAE{};
-
-
- template<class C> static yes test(SFINAE<C,&C::allocate>*);
- template<class C> static no test(...);
-
- public:
- static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
- };
-
- template<typename T>
- struct has_deallocate_interface
- {
- private:
- typedef std::true_type yes;
- typedef std::false_type no;
-
- template<typename U, bool (U::*f)(void*)> struct SFINAE{};
-
-
- template<class C> static yes test(SFINAE<C,&C::deallocate>*);
- template<class C> static no test(...);
-
- public:
- static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
- };
-
- template<typename T>
- using has_allocator_interface = constexpr_all_of<has_allocate_interface<T>::value,has_deallocate_interface<T>::value>;
- }
|