Files
fennec/include/fennec/lang/metasequences.h

247 lines
8.8 KiB
C++

// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file metasequences.h
/// \brief \ref fennec_lang_metasequences
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_SEQUENCES_H
#define FENNEC_LANG_SEQUENCES_H
///
/// \page fennec_lang_metasequences Metasequences
///
/// \brief This header is part of the metaprogramming library. It defines structures for metasequences of values, used during compile time.
///
/// \code #include <fennec/lang/metasequences.h> \endcode
///
/// <table width="100%" class="fieldtable" id="table_fennec_lang_metasequences">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::metasequence "metasequence<ValueT, Values...>"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::metasequence
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::integer_metasequence "integer_metasequence<IntT, Values...>"<br>
/// \ref fennec::make_integer_metasequence "typename make_integer_metasequence<IntT, N>::type"<br>
/// \ref fennec::make_integer_metasequence_t "make_integer_metasequence_t<IntT, N>"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::integer_metasequence
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::index_metasequence "index_metasequence<Indices...>"<br>
/// \ref fennec::make_index_metasequence "typename make_index_metasequence<N>::type"<br>
/// \ref fennec::make_index_metasequence_t "make_index_metasequence_t<N>"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::index_metasequence
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::concat_metasequence "typename concat_metasequence<metasequenceT0, metasequenceT1>::type"<br>
/// \ref fennec::concat_metasequence_t "concat_metasequence_t<metasequenceT0, metasequenceT1>"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::concat_metasequence
///
/// </table>
///
#include <fennec/lang/type_traits.h>
namespace fennec
{
// fennec::metasequence ====================================================================================================
///
/// \brief metaprogramming sequence
///
/// \details Stores a sequence of values of type \f$ValueT\f$ as a template pack.
/// You can access the parameter pack in another template function, i.e.
/// \code{cpp}
/// template<typename TypeT, TypeT...Values>
/// constexpr TypeT summation(metasequence<TypeT, Values...>)
/// {
/// return (Values + ...);
/// }
/// \endcode
/// \tparam ValueT type of the values
/// \tparam Values sequence values
template<typename ValueT, ValueT...Values> struct metasequence
{
/// \brief type of the metasequence
using value_type = ValueT;
/// \brief self-referential type
using type = metasequence;
///
/// \brief returns the number of elements
///
/// \return number of elements in the array
inline static constexpr size_t size() noexcept {
return sizeof...(Values);
}
};
// fennec::integer_metasequence ============================================================================================
///
/// \brief metaprogramming integral metasequence
///
/// \details A `fennec::metasequence` specialized integer types.
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>```
/// \tparam Values sequence values
template<typename IntT, IntT...Values> requires(is_integral_v<IntT>)
struct integer_metasequence : metasequence<IntT, Values...>
{
/// \brief type of the sequence
using value_type = IntT;
/// \brief self-referential type
using type = integer_metasequence;
///
/// \brief returns the number of elements
///
/// \return number of elements in the array
inline static constexpr size_t size() noexcept {
return sizeof...(Values);
}
};
///
/// \brief generate a fennec::integer_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$
///
/// \details
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>```
/// \tparam N size of the metasequence to generate
template<typename IntT, size_t N> struct make_integer_metasequence;
///
/// \brief shorthand for ```typename make_integer_sequence<T, N>::type```
template<typename IntT, size_t N> using make_integer_metasequence_t = typename make_integer_metasequence<IntT, N>::type;
// fennec::index_metasequence ==============================================================================================
///
/// \brief metaprogramming integral metasequence
///
/// \details A `fennec::integer_metasequence` specialized for sequences of `size_t` indices.
/// \tparam Indices sequence values
template<size_t...Indices> struct index_metasequence : integer_metasequence<size_t, Indices...>
{
/// \brief type of the sequence
using value_type = size_t;
/// \brief self-referential type
using type = index_metasequence;
///
/// \brief returns the number of elements
///
/// \return number of elements in the array
inline static constexpr size_t size() noexcept {
return sizeof...(Indices);
}
};
///
/// \brief generate a fennec::index_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$
///
/// \details
/// \tparam T type of the values, must satisfy ```fennec::is_integral<T>```
/// \tparam N size of the sequence to generate
template<size_t N> struct make_index_metasequence;
///
/// \brief shorthand for ```typename make_index_metasequence<N>::type```
template<size_t N> using make_index_metasequence_t = typename make_index_metasequence<N>::type;
// fennec::concat_metasequence =============================================================================================
///
/// \brief concatenate two metasequences
///
/// \details A tool for concatenating two `fennec::metasequence` types.
/// \tparam SequenceT0 lhs
/// \tparam SequenceT1 rhs
template<typename SequenceT0, typename SequenceT1> struct concat_metasequence;
///
/// \brief shorthand for ```typename concat_metasequence<SequenceT0, SequenceT1>::type```
template<typename SequenceT0, typename SequenceT1> using concat_metasequence_t
= typename concat_metasequence<SequenceT0, SequenceT1>::type;
// Internal ============================================================================================================
// Implementation for Generating an integer_sequence
template<typename T, size_t N> struct make_integer_metasequence : concat_metasequence_t<make_integer_metasequence_t<T, N / 2>, make_integer_metasequence_t<T, N - N / 2>>{};
// Base Case of N=0
template<typename T> struct make_integer_metasequence<T, 0> : integer_metasequence<T> {};
// Base Case of N=1
template<typename T> struct make_integer_metasequence<T, 1> : integer_metasequence<T, 0>{};
// Implementation for Generating an index_sequence
template<size_t N> struct make_index_metasequence : concat_metasequence_t<make_index_metasequence_t<N / 2>, make_index_metasequence_t<N - N / 2>>{};
// Base Case of N=0
template<> struct make_index_metasequence<0> : index_metasequence<> {};
// Base Case of N=1
template<> struct make_index_metasequence<1> : index_metasequence<0>{};
// Specialization for integer sequences
template<typename T, T...SequenceV0, T...SequenceV1>
struct concat_metasequence<integer_metasequence<T, SequenceV0...>, integer_metasequence<T, SequenceV1...>>
: integer_metasequence<T, SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
// Specialization for index sequences
template<size_t...SequenceV0, size_t...SequenceV1>
struct concat_metasequence<index_metasequence<SequenceV0...>, index_metasequence<SequenceV1...>>
: index_metasequence<SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
}
#endif // FENNEC_LANG_SEQUENCES_H