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