File indexing completed on 2024-05-12 15:57:03

0001 /*
0002  *  SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef KISMPL_H
0008 #define KISMPL_H
0009 
0010 #include <tuple>
0011 #include <utility>
0012 
0013 /**
0014  * 'kismpl' stands for kis-meta-program-library
0015  */
0016 namespace kismpl {
0017 namespace detail {
0018 
0019 template <class F, class Tuple, std::size_t... I>
0020 void apply_impl(F f, Tuple&& t, std::index_sequence<I...>)
0021 {
0022     f(std::get<I>(std::forward<Tuple>(t))...);
0023 }
0024 
0025 template <typename R, class F, class Tuple, std::size_t... I>
0026 R apply_r_impl(F f, Tuple&& t, std::index_sequence<I...>)
0027 {
0028     return f(std::get<I>(std::forward<Tuple>(t))...);
0029 }
0030 }  // namespace detail
0031 
0032 /**
0033  * Calls function \p f by passing the content of tuple \t as
0034  * distinct arguments.
0035  *
0036  * This is a simplified version of C++17's std::apply() routine.
0037  * It supports only standard function (not pointer-to-members)
0038  * without any return value.
0039  */
0040 template <class F, class Tuple>
0041 void apply(F&& f, Tuple&& t)
0042 {
0043     detail::apply_impl(
0044         std::forward<F>(f), std::forward<Tuple>(t),
0045         std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
0046 }
0047 
0048 template <typename R, class F, class Tuple>
0049 R apply_r(F&& f, Tuple&& t)
0050 {
0051     return detail::apply_r_impl<R>(
0052         std::forward<F>(f), std::forward<Tuple>(t),
0053         std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
0054 }
0055 
0056 
0057 namespace detail {
0058 
0059 template<std::size_t ...Idx>
0060 struct make_index_sequence_from_1_impl;
0061 
0062 template<std::size_t num, std::size_t ...Idx>
0063 struct make_index_sequence_from_1_impl<num, Idx...> {
0064     using type = typename make_index_sequence_from_1_impl<num - 1, num, Idx...>::type;
0065 };
0066 
0067 template<std::size_t ...Idx>
0068 struct make_index_sequence_from_1_impl<0, Idx...> {
0069     using type = std::index_sequence<Idx...>;
0070 };
0071 
0072 }  // namespace detail
0073 
0074 /**
0075  * Creates an index sequence in range 1, 2, 3, ..., Num
0076  *
0077  * Same as std::make_index_sequence, but starts counting
0078  * from 1 instead of 0.
0079  */
0080 template<std::size_t Num>
0081 using make_index_sequence_from_1 =
0082     typename detail::make_index_sequence_from_1_impl<Num>::type;
0083 
0084 }
0085 
0086 #endif // KISMPL_H