256 lines
7.1 KiB
C++
256 lines
7.1 KiB
C++
#pragma once
|
|
|
|
|
|
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
|
|
|
/* FINITE-STATE MACHINE UTILITY TYPES DEFINITIONS:
|
|
* std::pair sequence holder, unique-type tuple ... */
|
|
|
|
|
|
#include <limits>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
namespace mcc
|
|
{
|
|
|
|
namespace traits
|
|
{
|
|
|
|
// A CONCEPT DEFINITION FOR std::pair
|
|
template <typename T>
|
|
concept std_pair_c = requires(T t) {
|
|
[]<typename T1, typename T2>(std::type_identity<std::pair<T1, T2>>) {
|
|
|
|
}(std::type_identity<std::remove_cvref_t<T>>());
|
|
};
|
|
|
|
|
|
} // namespace traits
|
|
|
|
|
|
namespace fsm
|
|
{
|
|
|
|
/* A TYPE TO HOLD COMPILE-TIME SEQUENCE OF std::pair (PAIR-SEQUENCE HOLDER)
|
|
* internaly sequence is a std::tuple<std::pair<F1, S1>, std::pair<F2, S2>, ... std::pair<FN, SN>,>
|
|
i.e. std::pair.first field type of sequence elements may be of different types,
|
|
the same is for std::pair.second field
|
|
*/
|
|
// template <traits::std_pair_c... pairs>
|
|
// struct pair_holder_t;
|
|
|
|
// template <traits::std_pair_c head, traits::std_pair_c... tail>
|
|
// struct pair_holder_t<head, tail...> {
|
|
// // using self_t = pair_holder_t<head, tail...>;
|
|
// // using self_data_t = std::tuple<head, tail...>;
|
|
// typedef pair_holder_t<head, tail...> self_t;
|
|
// typedef std::tuple<head, tail...> sequence_t;
|
|
// };
|
|
|
|
// template <>
|
|
// struct pair_holder_t<> {
|
|
// // using self_data_t = std::tuple<>;
|
|
// typedef std::tuple<> sequence_t;
|
|
// constexpr static bool valid = true;
|
|
// };
|
|
|
|
template <traits::std_pair_c... pairs>
|
|
using pair_holder_t = std::tuple<pairs...>;
|
|
|
|
} // namespace fsm
|
|
|
|
|
|
namespace traits
|
|
{
|
|
|
|
// PAIR-SEQUENCE HOLDER CONCEPT DEFINITION
|
|
template <typename T>
|
|
concept pair_holder_c = requires {
|
|
[]<mcc::traits::std_pair_c... Ts>(std::type_identity<fsm::pair_holder_t<Ts...>>) {
|
|
//
|
|
}(std::type_identity<std::remove_cvref_t<T>>());
|
|
};
|
|
|
|
} // namespace traits
|
|
|
|
|
|
namespace fsm
|
|
{
|
|
|
|
/* A CLASS TO FIND TYPE OF pair.second FIELD BY ITS pair.first ONE IN PAIR-SEQUENCE */
|
|
|
|
template <typename FirstT, traits::pair_holder_c PHLDT>
|
|
struct pair_holder_find_t;
|
|
|
|
template <typename FirstT, typename CurrentFirstT, typename SecondT, mcc::traits::std_pair_c... tail>
|
|
struct pair_holder_find_t<FirstT, pair_holder_t<std::pair<CurrentFirstT, SecondT>, tail...>>
|
|
: pair_holder_find_t<FirstT, pair_holder_t<tail...>> {
|
|
};
|
|
|
|
template <typename FirstT>
|
|
struct pair_holder_find_t<FirstT, pair_holder_t<>> {
|
|
typedef std::nullptr_t result_t;
|
|
};
|
|
|
|
template <typename FirstT, typename SecondT, mcc::traits::std_pair_c... tail>
|
|
struct pair_holder_find_t<FirstT, pair_holder_t<std::pair<FirstT, SecondT>, tail...>> {
|
|
typedef SecondT result_t;
|
|
};
|
|
|
|
|
|
|
|
/* A CLASS TO GET ALL pair.first FIELD TYPES IN PAIR-SEQUENCE */
|
|
|
|
template <traits::pair_holder_c PHLDT>
|
|
struct pair_holder_first_t;
|
|
|
|
template <typename FirstT, typename SecondT, mcc::traits::std_pair_c... tail>
|
|
struct pair_holder_first_t<pair_holder_t<std::pair<FirstT, SecondT>, tail...>> {
|
|
typedef decltype(std::tuple_cat(
|
|
std::declval<std::tuple<FirstT>>(),
|
|
std::declval<typename pair_holder_first_t<pair_holder_t<tail...>>::first_t>())) first_t;
|
|
};
|
|
|
|
|
|
template <>
|
|
struct pair_holder_first_t<pair_holder_t<>> {
|
|
typedef std::tuple<> first_t;
|
|
};
|
|
|
|
|
|
/* A CLASS TO GET ALL pair.second TYPES IN PAIR-SEQUENCE */
|
|
|
|
template <traits::pair_holder_c PHLDT>
|
|
struct pair_holder_second_t;
|
|
|
|
template <typename FirstT, typename SecondT, mcc::traits::std_pair_c... tail>
|
|
struct pair_holder_second_t<pair_holder_t<std::pair<FirstT, SecondT>, tail...>> {
|
|
typedef decltype(std::tuple_cat(
|
|
std::declval<std::tuple<SecondT>>(),
|
|
std::declval<typename pair_holder_second_t<pair_holder_t<tail...>>::second_t>())) second_t;
|
|
};
|
|
|
|
|
|
template <>
|
|
struct pair_holder_second_t<pair_holder_t<>> {
|
|
typedef std::tuple<> second_t;
|
|
};
|
|
|
|
|
|
|
|
/* A TYPE TO IMPLEMENT TUPLE OF UNIQUE TYPES */
|
|
|
|
template <typename... TYPEs>
|
|
class unique_tuple_t
|
|
{
|
|
template <typename IT, typename UniqTupleT>
|
|
struct in_tuple : in_tuple<IT, typename UniqTupleT::tuple_t> {
|
|
};
|
|
|
|
template <typename IT, typename... Ts>
|
|
struct in_tuple<IT, std::tuple<Ts...>> : std::disjunction<std::is_same<IT, Ts>...> {
|
|
};
|
|
|
|
// insert
|
|
template <typename IT, typename UniqTupleT, bool = in_tuple<IT, UniqTupleT>::value>
|
|
struct insert;
|
|
|
|
template <typename IT, typename... Ts>
|
|
struct insert<IT, std::tuple<Ts...>, false> {
|
|
typedef std::tuple<IT, Ts...> tuple_t;
|
|
typedef std::tuple<> non_unique_t;
|
|
};
|
|
|
|
template <typename IT, typename... Ts>
|
|
struct insert<IT, std::tuple<Ts...>, true> {
|
|
typedef std::tuple<Ts...> tuple_t;
|
|
typedef std::tuple<IT> non_unique_t;
|
|
};
|
|
|
|
|
|
// merge
|
|
template <typename ITupleT, typename OTupleT>
|
|
struct merge;
|
|
|
|
template <typename MT, typename... MTs, typename... OTs>
|
|
struct merge<std::tuple<MT, MTs...>, std::tuple<OTs...>> {
|
|
typedef merge<std::tuple<MTs...>, std::tuple<OTs...>> tail_t;
|
|
typedef insert<MT, typename tail_t::tuple_t> curr_tuple_t;
|
|
|
|
typedef typename curr_tuple_t::tuple_t tuple_t;
|
|
typedef decltype(std::tuple_cat(std::declval<typename curr_tuple_t::non_unique_t>(),
|
|
std::declval<typename tail_t::non_unique_t>())) non_unique_t;
|
|
};
|
|
|
|
template <typename... MTs>
|
|
struct merge<std::tuple<>, std::tuple<MTs...>> {
|
|
typedef std::tuple<MTs...> tuple_t;
|
|
typedef std::tuple<> non_unique_t;
|
|
};
|
|
|
|
public:
|
|
typedef typename merge<std::tuple<TYPEs...>, std::tuple<>>::tuple_t tuple_t;
|
|
typedef typename merge<std::tuple<TYPEs...>, std::tuple<>>::non_unique_t non_unique_t;
|
|
};
|
|
|
|
} // namespace fsm
|
|
|
|
|
|
namespace traits
|
|
{
|
|
|
|
// UNIQUE-TYPES TUPLE CONCEPT DEFINITION
|
|
template <typename T>
|
|
concept unique_tuple_c = requires {
|
|
[]<typename... Ts>(std::type_identity<fsm::unique_tuple_t<Ts...>>) {}(std::type_identity<std::remove_cvref_t<T>>());
|
|
};
|
|
|
|
} // namespace traits
|
|
|
|
|
|
namespace fsm
|
|
{
|
|
|
|
// GET INDEX OF GIVEN TYPE IN UNIQUE TUPLE
|
|
namespace details
|
|
{
|
|
|
|
// template <typename T, mcc::traits::unique_tuple_c UT, std::size_t I = 0>
|
|
template <typename T, typename TupleT, std::size_t I = 0>
|
|
struct unique_tuple_type_index_helper_t;
|
|
|
|
|
|
template <typename T, typename HeadT, typename... TailT, std::size_t I>
|
|
struct unique_tuple_type_index_helper_t<T, std::tuple<HeadT, TailT...>, I> {
|
|
constexpr static std::size_t index = unique_tuple_type_index_helper_t<T, std::tuple<TailT...>, I + 1>::index;
|
|
};
|
|
|
|
|
|
template <typename T, typename... TailT, std::size_t I>
|
|
struct unique_tuple_type_index_helper_t<T, std::tuple<T, TailT...>, I> {
|
|
constexpr static std::size_t index = I;
|
|
};
|
|
|
|
template <typename T, std::size_t I>
|
|
struct unique_tuple_type_index_helper_t<T, std::tuple<>, I> {
|
|
constexpr static std::size_t index = std::numeric_limits<std::size_t>::max();
|
|
static_assert(false, "INVALID INPUT TYPE!");
|
|
};
|
|
|
|
} // namespace details
|
|
|
|
|
|
template <typename T, mcc::traits::unique_tuple_c UT>
|
|
struct unique_tuple_type_index_t : details::unique_tuple_type_index_helper_t<T, typename UT::tuple_t, 0> {
|
|
};
|
|
|
|
template <typename T, mcc::traits::unique_tuple_c UT>
|
|
constexpr static std::size_t unique_tuple_type_index_v = unique_tuple_type_index_t<T, typename UT::tuple_t>::index;
|
|
|
|
} // namespace fsm
|
|
|
|
|
|
} // namespace mcc
|