diff options
Diffstat (limited to 'include/estd/IntegerSequence.hpp')
-rw-r--r-- | include/estd/IntegerSequence.hpp | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/include/estd/IntegerSequence.hpp b/include/estd/IntegerSequence.hpp new file mode 100644 index 0000000..a0776f5 --- /dev/null +++ b/include/estd/IntegerSequence.hpp @@ -0,0 +1,229 @@ +/** + * \file + * \brief IntegerSequence template class header + * + * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info + * + * \par License + * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not + * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef ESTD_INTEGERSEQUENCE_HPP_ +#define ESTD_INTEGERSEQUENCE_HPP_ + +#include <type_traits> + +namespace estd +{ + +/** + * \brief Compile-time sequence of integers + * + * Similar to std::integer_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence + * + * \tparam T is an integer type to use for the elements of the sequence + * \tparam Integers is a non-type parameter pack representing the sequence + */ + +template<typename T, T... Integers> +class IntegerSequence +{ +public: + + /// integer type used for the elements of the sequence + using value_type = T; + + /** + * \return number of elements in the sequence + */ + + constexpr static std::size_t size() noexcept + { + return sizeof...(Integers); + }; +}; + +/** + * \brief Compile-time sequence of std::size_t elements + * + * Similar to std::index_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence + * + * \tparam Indexes is a non-type parameter pack representing the sequence + */ + +template<std::size_t... Indexes> +using IndexSequence = IntegerSequence<std::size_t, Indexes...>; + +namespace internal +{ + +/** + * \brief IntegerSequence with two internal type aliases. + * + * \tparam T is an integer type to use for the elements of the sequence + * \tparam Integers is a non-type parameter pack representing the sequence + */ + +template<typename T, T... Integers> +struct TypedSequence : IntegerSequence<T, Integers...> +{ + /// type of base class + using base = IntegerSequence<T, Integers...>; + + /// type of class + using type = TypedSequence; +}; + +/** + * \brief TypedSequence with doubled number of elements + * + * \tparam Sequence is the type of sequence that will be doubled + */ + +template<typename Sequence> +struct DoubledIntegerSequence; + +/** + * \brief TypedSequence with doubled number of elements + * + * Specialization for TypedSequence. + * + * \tparam T is an integer type to use for the elements of the sequence + * \tparam Integers is a non-type parameter pack representing the sequence + */ + +template<typename T, T... Integers> +struct DoubledIntegerSequence<TypedSequence<T, Integers...>> +{ + /// TypedSequence with doubled number of elements - TypedSequence<T, 0, 1, ..., N - 1> is turned into + /// TypedSequence<T, 0, 1, ..., N - 1, N, N + 1, ..., 2 * N - 1> + using type = TypedSequence<T, Integers..., (sizeof...(Integers) + Integers)...>; +}; + +/** + * \brief TypedSequence optionally extended by one element + * + * \tparam Extend selects whether the sequence will be extended by one element (true) or not (false) + * \tparam Sequence is the type of sequence that will optionally be extended + */ + +template<bool Extend, typename Sequence> +struct ExtendedIntegerSequence +{ + /// same as \a Sequence + using type = Sequence; +}; + +/** + * \brief TypedSequence optionally extended by one element + * + * Specialization for the case with extending. + * + * \tparam T is an integer type to use for the elements of the sequence + * \tparam Integers is a non-type parameter pack representing the sequence + */ + +template<typename T, T... Integers> +struct ExtendedIntegerSequence<true, TypedSequence<T, Integers...>> +{ + /// sequence extended by one element - TypedSequence<T, 0, 1, ..., N - 1> is turned into + /// TypedSequence<T, 0, 1, ..., N - 1, N> + using type = TypedSequence<T, Integers..., sizeof...(Integers)>; +}; + +/** + * \brief Implementation of generator of IntegerSequence types + * + * Generates TypedSequence<T, 0, 1, ..., N - 1> type. + * + * \tparam T is an integer type to use for the elements of the sequence + * \tparam N is the requested number of elements in the sequence + */ + +template<typename T, std::size_t N> +struct MakeIntegerSequenceImplementation : + ExtendedIntegerSequence<N % 2 != 0, + typename DoubledIntegerSequence<typename MakeIntegerSequenceImplementation<T, N / 2>::type>::type> +{ + +}; + +/** + * \brief Implementation of generator of IntegerSequence types + * + * Specialization for terminal case - 0 elements - generates TypedSequence<T> type. + * + * \tparam T is an integer type to use for the elements of the sequence + */ + +template<typename T> +struct MakeIntegerSequenceImplementation<T, 0> +{ + /// empty TypedSequence<T> type + using type = TypedSequence<T>; +}; + +/** + * \brief Wrapper for MakeIntegerSequenceImplementation that ensures \a N is non-negative + * + * Generates TypedSequence<T, 0, 1, ..., N - 1> type. + * + * \tparam T is an integer type to use for the elements of the sequence + * \tparam N is the requested number of elements in the sequence, must be non-negative + */ + +template<typename T, T N> +struct MakeIntegerSequenceImplementationWrapper : + std::enable_if<N >= 0, MakeIntegerSequenceImplementation<T, static_cast<std::size_t>(N)>>::type +{ + static_assert(N >= 0, "Number of elements in the sequence must be non-negative!"); +}; + +} // namespace internal + +/** + * \brief Generator of IntegerSequence types + * + * Similar to std::make_integer_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence + * + * Whole implementation is based on code from http://stackoverflow.com/a/20101039/157344 + * + * Generates IntegerSequence<T, 0, 1, ..., N - 1> type. + * + * \tparam T is an integer type to use for the elements of the sequence + * \tparam N is the requested number of elements in the sequence + */ + +template<typename T, T N> +using MakeIntegerSequence = typename internal::MakeIntegerSequenceImplementationWrapper<T, N>::type::base; + +/** + * \brief Generator of IndexSequence types + * + * Similar to std::make_index_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence + * + * Generates IndexSequence<0, 1, ..., N - 1> type. + * + * \tparam N is the requested number of elements in the sequence + */ + +template<std::size_t N> +using MakeIndexSequence = MakeIntegerSequence<std::size_t, N>; + +/** + * \brief Generator of IndexSequence types + * + * Similar to std::index_sequence_for from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence + * + * Generates IndexSequence<0, 1, ..., sizeof...(T) - 1> type. + * + * \tparam T is the type parameter pack for which an index sequence of the same length will be generated + */ + +template<typename... T> +using IndexSequenceFor = MakeIndexSequence<sizeof...(T)>; + +} // namespace estd + +#endif // ESTD_INTEGERSEQUENCE_HPP_ |