247 lines
8.8 KiB
C++
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
|