Page MenuHomePhorge

type_list.hpp
No OneTemporary

Size
12 KB
Referenced Files
None
Subscribers
None

type_list.hpp

/***************************************************************************//**
*
* \file rosa/support/type_list.hpp
*
* \author David Juhasz (david.juhasz@tuwien.ac.at)
*
* \date 2017
*
* \brief Facilities for types representing lists of types.
*
* \note This implementation is partially based on the `type_list`
* implementation of CAF.
* \todo Check license.
*
******************************************************************************/
#ifndef ROSA_SUPPORT_TYPE_LIST_HPP
#define ROSA_SUPPORT_TYPE_LIST_HPP
#include "rosa/support/debug.hpp"
#include "rosa/support/types.hpp"
#include <type_traits>
namespace rosa {
/// A list of types.
///
/// \tparam Ts types to make a list of
template <typename... Ts> struct TypeList {
/// Ctor, needs to do nothing.
constexpr TypeList(void) {}
};
/// The empty `rosa::Typelist`.
using EmptyTypeList = TypeList<>;
/// \defgroup TypeListAtImpl
/// \brief Gets the type at index `Pos` from a list of types.
///
/// \note Only to be used by the implementation of `rosa::TypeListAt`.
///@{
/// Declaration of the template.
///
/// \tparam Pos index to take the element from
/// \tparam Ts types
template <size_t Pos, typename... Ts> struct TypeListAtImpl;
/// Definition for the general case when `Pos` is not `0` and there is type in
/// the list.
template <size_t Pos, typename T, typename... Ts>
struct TypeListAtImpl<Pos, T, Ts...> {
using Type = typename TypeListAtImpl<Pos - 1, Ts...>::Type;
};
/// Specialization for the case when `Pos` is `0`˙.
template <typename T, typename... Ts> struct TypeListAtImpl<0, T, Ts...> {
using Type = T;
};
/// Specialization for the case when there is no more type.
///
/// In this case, the found type is `rosa::none_t`.
template <size_t Pos> struct TypeListAtImpl<Pos> { using Type = none_t; };
///@}
/// \defgroup TypeListAt
/// \brief Gets the element at index `Pos` of `List`.
///
///
/// The type at index `Pos` in a `rosa::TypeList` `List` can be obtained as
/// \code
/// typename TypeListAt<List, Pos>::Type
/// \endcode
///
/// \note The resulting type is `rosa::none_t` if \code
/// TypeListSize<List>::Value < Pos
/// \endcode
///@{
/// Declaration of the template.
///
/// \tparam List `TypeList` to take an element from
/// \tparam Pos index to take the element from
template <typename List, size_t Pos> struct TypeListAt;
/// Implementation using `rosa::TypeListAtImpl`.
template <size_t Pos, typename... Ts> struct TypeListAt<TypeList<Ts...>, Pos> {
using Type = typename TypeListAtImpl<Pos, Ts...>::Type;
};
///@}
/// \defgroup TypeListIndexOfImpl
/// \brief Tells the index of the first occurence of a type in a list of types.
///
/// \note Only to be used by the implementation of `rosa::TypeListIndexOf`.
///@{
/// Declaration of the template.
///
/// \tparam Pos the number types already being checked from the beginning of the
/// list
/// \tparam X type to search for
/// \tparam Ts remaining list of types
template <size_t Pos, typename X, typename... Ts> struct TypeListIndexOfImpl;
/// Specialization for the case when the list is over.
///
/// In this case, the found index is `-1`.
template <size_t Pos, typename X> struct TypeListIndexOfImpl<Pos, X> {
static constexpr int Value = -1;
};
/// Specialization for the case when the first type in the remaining list
/// is a match.
template <size_t Pos, typename X, typename... Ts>
struct TypeListIndexOfImpl<Pos, X, X, Ts...> {
static constexpr int Value = Pos;
};
/// Implementation for the general case when need to continue looking.
template <size_t Pos, typename X, typename T, typename... Ts>
struct TypeListIndexOfImpl<Pos, X, T, Ts...> {
static constexpr int Value = TypeListIndexOfImpl<Pos + 1, X, Ts...>::Value;
};
///@}
/// \defgroup TypeListIndexOf
/// \brief Tells the index of the first occurence of type in a `rosa::TypeList`.
///
/// The index of the first occurence of type `T` in `rosa::TypeList` `List` can
/// be obtained as \code
/// TypeListIndexOf<List, T>::Value
/// \endcode
///
/// \note The resulting index is `-1` if `T` is not present in `List`.
///@{
/// Declaration of the template.
///
/// \tparam List `TypeList` to search in
/// \tparam T type to search for
template <typename List, typename T> struct TypeListIndexOf;
/// Implementation of the template using `rosa::TypeListIndexOfImpl`.
template <typename... Ts, typename T>
struct TypeListIndexOf<TypeList<Ts...>, T> {
static constexpr int Value = TypeListIndexOfImpl<0, T, Ts...>::Value;
};
///@}
/// \defgroup TypeListHead
/// \brief Gets the first element of a `rosa::TypeList`.
///
/// The first element of a `rosa::TypeList` `List` can be obtained as \code
/// typename TypeListHead<List>::Type
/// \endcode
///
/// \note The resulting type is `rosa::none_t` if `List` is the
/// `rosa::EmptyTypeList`.
///@{
/// Declaration of the template.
///
/// \tparam List `TypeList` to get the first element of
template <typename List> struct TypeListHead;
/// Specialization for `rosa::EmptyTypeList`.
///
/// In this case, the found type is `rosa::none_t`.
template <> struct TypeListHead<EmptyTypeList> { using Type = none_t; };
/// Implementation for a non-empty `rosa::TypeList`.
template <typename T, typename... Ts>
struct TypeListHead<TypeList<T, Ts...>> {
using Type = T;
};
///@}
/// \defgroup TypeListTail
///
/// \brief Gets the tail of a `rosa::TypeList`.
///
/// The tail of a `rosa::TypeList` `List`, that is `List` except for its first
/// element, can be obtained as \code
/// typename TypeListTail<List>::Type
/// \endcode
///
/// \note If `List` is the `rosa::EmptyTypeList`, then the resulting type is
/// also `rosa::EmptyTypeList`.
///@{
/// Declaration of the template.
///
/// \tparam List `TypeList` to take the tail of
template <typename List> struct TypeListTail;
/// Specialization for the `rosa::EmptyTypeList`.
///
/// In this case, the resulting type is `rosa::EmptyTypeList`.
template <> struct TypeListTail<EmptyTypeList> { using Type = EmptyTypeList; };
/// Implementation for a non-empty `rosa::TypeList`.
template <typename T, typename... Ts>
struct TypeListTail<TypeList<T, Ts...>> {
using Type = TypeList<Ts...>;
};
///@}
/// \defgroup TypeListPush
/// \brief Extends a `rosa::TypeList` with a type.
///
/// Whether the new type is pushed in the front or in the back of the
/// `rosa::TypeList` depends on the order of template arguments, as shown in the
/// following example: \code
/// using List = TypeList<A>
/// typename TypeListPush<List, T>::Type; // TypeList<A, T>
/// typename TypeListPush<T, List>::Type; // TypeList<T, A>
/// \endcode
///@{
/// Declaration of the template.
///
/// \tparam P a type if `Q` is a `rosa::TypeList`, a `rosa::TypeList` otherwise
/// \tparam Q a type if `P` is a `rosa::TypeList`, a `rosa::TypeList` otherwise
template <typename P, typename Q>
struct TypeListPush;
/// Implementation for the case when pushing at the back of the
/// `rosa::TypeList`.
template <typename... Ts, typename T>
struct TypeListPush<TypeList<Ts...>, T> {
using Type = TypeList<Ts...,T>;
};
/// Implementation for the case when pushing to the front of the
/// `rosa::TypeList`.
template <typename T, typename... Ts>
struct TypeListPush<T, TypeList<Ts...>> {
using Type = TypeList<T, Ts...>;
};
///@}
/// \defgroup TypeListDrop
/// \brief Drops some elements from the beginning of a `rosa::TypeList`.
///
/// The first `N` types of a `rosa::TypeList` `List` can be dropped as \code
/// typename TypeListDrop<N, List>::Type
/// \endcode
///@{
/// Declaration of the template.
///
/// \tparam N number of types to drop
/// \tparam List `TypeList` to drop the first `N` element of
template <size_t N, typename List> struct TypeListDrop;
/// Specialization for the `rosa::EmptyTypeList`.
template <size_t N> struct TypeListDrop<N, EmptyTypeList> {
using Type = EmptyTypeList;
};
/// Implementation for a non-empty `rosa::TypeList`.
template <size_t N, typename T, typename... Ts>
struct TypeListDrop<N, TypeList<T, Ts...>> {
using Type = typename std::conditional<
N == 0, TypeList<Ts...>,
typename TypeListDrop<N - 1, TypeList<Ts...>>::Type>::type;
};
///@}
/// \defgroup TypeListSize
/// \brief Tells the number of types stored in a `rosa::TypeList`.
///
/// The size of a `rosa::TypeList` `List` can be obtained as \code
/// TypeListSize<List>::Value
/// \endcode
///@{
/// Declaration of the template.
///
/// \tparam List `TypeList` to get the size of
template <typename List>
struct TypeListSize;
/// Implementation of the template.
template <typename... Ts> struct TypeListSize<TypeList<Ts...>> {
static constexpr size_t Value = sizeof...(Ts);
};
template <typename... Ts> constexpr size_t TypeListSize<TypeList<Ts...>>::Value;
///@}
/// Tests whether a `rosa::TypeList` is empty.
///
/// \tparam List the `TypeList` to check
template <typename List> struct TypeListEmpty {
/// Denotes whether `List` is an empty `rosa::TypeList` or not.
static constexpr bool Value = std::is_same<EmptyTypeList, List>::value;
};
/// \defgroup TypeListContains
/// \brief Tells if a `rosa::TypeList` contains a type.
///
/// Whether a `rosa::TypeList` `List` contains the type `T` can be checked as
/// \code
/// TypeListContains<List, T>::Value
/// \endcode
///@{
/// Declaration of the template.
///
/// \tparam List `TypeList` to search in
/// \tparam T type to search for
template <typename List, typename T> struct TypeListContains;
/// Implementation of the template.
template <typename... Ts, typename T>
struct TypeListContains<TypeList<Ts...>, T> {
static constexpr bool Value =
std::conditional<TypeListIndexOf<TypeList<Ts...>, T>::Value == -1,
std::false_type, std::true_type>::type::value;
};
///@}
/// \defgroup TypeListSubsetOf
/// \brief Tells if a `rosa::TypeList` is a subset of another one.
///
/// Whether a `rosa::TypeList` `ListA` is a subset of another `rosa::TypeList`
/// `ListB` can be checked as \code
/// TypeListSubsetOf<ListA, ListB>::Value
/// \endcode
///@{
/// Declaration of the template.
///
/// \tparam ListA `TypeList` to check if is a subset of `ListB`
/// \tparam ListB `TypeList` to check if is a superset of `ListA`
/// \tparam Fwd always use the default value!
template <typename ListA, typename ListB, bool Fwd = true>
struct TypeListSubsetOf;
/// Specialization for the case when all the elements of the original `ListA`
/// was found in `ListB`.
template <typename List>
struct TypeListSubsetOf<EmptyTypeList, List, true> {
static constexpr bool Value = true;
};
/// Specializaton for the case when an element of the original `ListA` cannot be
/// found in `ListB`.
template <typename ListA, typename ListB>
struct TypeListSubsetOf<ListA, ListB, false> {
static constexpr bool Value = false;
};
/// Definition for the general case.
template <typename T, typename... Ts, typename List>
struct TypeListSubsetOf<TypeList<T, Ts...>, List>
: TypeListSubsetOf<TypeList<Ts...>, List,
TypeListContains<List, T>::Value> {};
///@}
/// \defgroup TypeListFindImpl
/// \brief Finds the first type in a list of types that satisfies a predicate.
///
/// \note Only to be used by the implementation of `rosa::TypeListFind`.
///@{
/// Declaration of the template.
///
/// \tparam Pred the predicate to check types against
/// \tparam Ts list of types to check
template <template <typename> class Pred, typename... Ts>
struct TypeListFindImpl;
/// Specialization for the case when no more types remain to check.
template <template <typename> class Pred> struct TypeListFindImpl<Pred> {
using Type = none_t;
};
/// Implementation for the general case when there is a type to check.
template <template <typename> class Pred, typename T, typename... Ts>
struct TypeListFindImpl<Pred, T, Ts...> {
using Type = typename std::conditional<
Pred<T>::Value, T, typename TypeListFindImpl<Pred, Ts...>::Type>::type;
};
///@}
/// \defgroup TypeListFind
/// \brief Finds the first element satisfying a predicate in a `rosa::TypeList`.
///
/// The first type satisfying a predicate `Pred` in a `rosa::TypeList` `List`
/// can be obtained as \code
/// typename TypeListFind<List, Pred>::Type
/// \endcode
///
/// \note The resulting type is `rosa::none_t` if no type in `List` satisfies
/// `Pred`.
///@{
/// Declaration of the template.
///
/// \tparam List `TypeList` to search in
/// \tparam Pred predicate to check elements against
template <typename List, template <typename> class Pred>
struct TypeListFind;
/// Implementation of the template using `rosa::TypeListFindImpl`.
template <typename... Ts, template <typename> class Pred>
struct TypeListFind<TypeList<Ts...>, Pred> {
using Type = typename TypeListFindImpl<Pred, Ts...>::Type;
};
///@}
} // End namespace rosa
#endif // ROSA_SUPPORT_TYPE_LIST_HPP

File Metadata

Mime Type
text/x-c++
Expires
Sun, May 31, 4:44 PM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
318458
Default Alt Text
type_list.hpp (12 KB)

Event Timeline