|
- /*!
- * \file pack.h
- * \brief Template meta-programming parameter pack container
- *
- * Copyright (C) 2018-2019 Christos Choutouridis
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #ifndef __utl_meta_idx_sequence_h__
- #define __utl_meta_idx_sequence_h__
-
- #include <utl/core/impl.h>
- #include <utl/meta/integral.h>
-
-
- /*!
- * \ingroup meta
- * \defgroup index_sequence
- */
- //! @{
-
- namespace utl {
- namespace meta {
-
- /*!
- * Class template integer_sequence
- */
- template<typename _Tp, _Tp... _Idx>
- struct integer_sequence {
- using value_type = _Tp;
- static constexpr size_t size() noexcept {
- return sizeof...(_Idx);
- }
- };
-
- //! Alias template index_sequence
- template<index_t... _Idx>
- using index_sequence = integer_sequence<index_t, _Idx...>;
-
- //! make_integer_sequence
- //! @{
- namespace detail {
- // Stores a tuple of indices
- template<size_t... Idxs> struct index_tuple { };
-
- // Concatenates two index_tuples.
- template<typename It1, typename It2> struct it_cat_;
-
- template<size_t... It1, size_t... It2>
- struct it_cat_ <index_tuple<It1...>, index_tuple<It2...>> {
- using type = index_tuple<It1..., (It2 + sizeof...(It1))...>;
- };
-
- // Builds an index_tuple<0, 1, 2, ..., _Num-1>.
- template<size_t _Num>
- struct make_index_tuple_
- : it_cat_<eval<make_index_tuple_<_Num / 2>>,
- eval<make_index_tuple_<_Num - _Num / 2>>>
- { };
- // termination specialization for 1
- template<>
- struct make_index_tuple_<1> {
- using type = index_tuple<0>;
- };
- // termination specialization for 0
- template<>
- struct make_index_tuple_<0> {
- using type = index_tuple<>;
- };
-
- // factory type
- template<typename _Tp, _Tp _Num,
- typename _ISeq = eval<make_index_tuple_<_Num>>>
- struct make_integer_sequence_;
-
- template<typename _Tp, _Tp _Num, size_t... _Idx>
- struct make_integer_sequence_<_Tp, _Num, index_tuple<_Idx...>> {
- static_assert( _Num >= 0,
- "Cannot make integer sequence of negative length" );
- using type = integer_sequence<_Tp, static_cast<_Tp>(_Idx)...>;
- };
- }
- //! Alias template make_integer_sequence
- //! Complexity \f$ O(log N) \f$
- template<typename _Tp, _Tp N>
- using make_integer_sequence = eval<detail::make_integer_sequence_<_Tp, N>>;
-
- //! Alias template make_index_sequence
- //! Complexity \f$ O(log N) \f$
- template<index_t N>
- using make_index_sequence = make_integer_sequence<index_t, N>;
-
- //! Alias template index_sequence_for
- //! Complexity \f$ O(log N) \f$
- //! where N is sizeof...(_Ts)
- template<typename... _Ts>
- using index_sequence_for = make_index_sequence<sizeof...(_Ts)>;
- //! @}
-
- }}
- //! @}
- #endif /* __utl_meta_idx_sequence_h__ */
|