GCC Code Coverage Report


Directory: include/kumi/
File: include/kumi/functional/bind.hpp
Date: 2026-10-14 16:33:56
Exec Total Coverage
Lines: 11 11 100.0%
Functions: 226 226 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 //==================================================================================================
2 /*
3 KUMI - Compact Tuple Tools
4 Copyright : KUMI Project Contributors
5 SPDX-License-Identifier: BSL-1.0
6 */
7 //==================================================================================================
8 #pragma once
9
10 namespace kumi
11 {
12 namespace _
13 {
14 enum class Binding
15 {
16 front,
17 back
18 };
19
20 template<Binding D, typename F, typename... Bound>
21 struct bind_t : leaf<static_cast<std::size_t>(-1), F>,
22 make_binder_t<std::make_index_sequence<sizeof...(Bound)>, Bound...>
23 {
24 static constexpr auto function_index = static_cast<std::size_t>(-1);
25 static constexpr auto seq = std::make_index_sequence<sizeof...(Bound)>{};
26
27 using binder_t = make_binder_t<std::make_index_sequence<sizeof...(Bound)>, Bound...>;
28 using func_t = leaf<function_index, F>;
29
30 848 template<typename... Args> KUMI_HIDDEN_ABI constexpr decltype(auto) operator()(Args&&... args) &
31 {
32 848 return impl(seq, *this, KUMI_FWD(args)...);
33 }
34
35 272 template<typename... Args> KUMI_HIDDEN_ABI constexpr decltype(auto) operator()(Args&&... args) const&
36 {
37 272 return impl(seq, *this, KUMI_FWD(args)...);
38 }
39
40 template<typename... Args> KUMI_HIDDEN_ABI constexpr decltype(auto) operator()(Args&&... args) &&
41 {
42 return impl(seq, std::move(*this), KUMI_FWD(args)...);
43 }
44
45 template<typename... Args> KUMI_HIDDEN_ABI constexpr decltype(auto) operator()(Args&&... args) const&&
46 {
47 return impl(seq, std::move(*this), KUMI_FWD(args)...);
48 }
49
50 template<std::size_t... Is, typename Self, typename... Args>
51 1120 KUMI_HIDDEN_ABI static constexpr decltype(auto) impl(std::index_sequence<Is...>, Self&& s, Args&&... args)
52 {
53 if constexpr (D == Binding::front)
54 {
55 336 return kumi::invoke(KUMI_FWD(s).func_t::operator()(std::integral_constant<size_t, function_index>{}),
56 KUMI_FWD(s).binder_t::operator()(std::integral_constant<std::size_t, Is>{})...,
57 336 KUMI_FWD(args)...);
58 }
59 else
60 {
61 784 return kumi::invoke(KUMI_FWD(s).func_t::operator()(std::integral_constant<size_t, function_index>{}),
62 KUMI_FWD(args)...,
63 784 KUMI_FWD(s).binder_t::operator()(std::integral_constant<std::size_t, Is>{})...);
64 }
65 }
66 };
67 }
68
69 //====================================================================================================================
70 /**
71 @ingroup kumi_functional
72 @brief Returns a callable object with `ts` bound as its leading arguments, reducing `c` arity.
73
74 @param c Callable object to be bound.
75 @param ts Elements to be bound as the leading arguments of `c`.
76 @return A callable object of lower arity invoking `c` with `ts` prefilled at the front.
77
78 @note Replaces std::bind_front to avoid depending on `functional`.
79 **/
80 //====================================================================================================================
81 template<typename C, typename... Ts>
82 KUMI_ABI constexpr auto bind_front(C&& c, Ts&&... ts)
83 noexcept(std::is_nothrow_move_constructible_v<std::decay_t<C>> &&
84 (std::is_nothrow_move_constructible_v<std::decay_t<Ts>> && ...))
85 requires(std::is_move_constructible_v<std::decay_t<C>> && (std::is_move_constructible_v<std::decay_t<Ts>> && ...))
86 {
87 168 return kumi::_::bind_t<kumi::_::Binding::front, std::decay_t<C>, std::decay_t<Ts>...>{KUMI_FWD(c), KUMI_FWD(ts)...};
88 }
89
90 //====================================================================================================================
91 /**
92 @ingroup kumi_functional
93 @brief Returns a callable object with `ts` bound as its trailing arguments, reducing `c` arity.
94
95 @param c Callable object to be bound.
96 @param ts Elements to be bound as the trailing arguments of `c`.
97 @return A callable object of lower arity invoking `c` with `ts` prefilled at the back.
98
99 @note Replaces std::bind_back to avoid depending on `functional`.
100 **/
101 //====================================================================================================================
102 template<typename C, typename... Ts>
103 KUMI_ABI constexpr auto bind_back(C&& c, Ts&&... ts)
104 noexcept(std::is_nothrow_move_constructible_v<std::decay_t<C>> &&
105 (std::is_nothrow_move_constructible_v<std::decay_t<Ts>> && ...))
106 requires(std::is_move_constructible_v<std::decay_t<C>> && (std::is_move_constructible_v<std::decay_t<Ts>> && ...))
107 {
108 405 return kumi::_::bind_t<kumi::_::Binding::back, std::decay_t<C>, std::decay_t<Ts>...>{KUMI_FWD(c), KUMI_FWD(ts)...};
109 }
110
111 template<typename C, typename... Ts>
112 KUMI_ABI constexpr auto bind(C&& c, Ts&&... ts)
113 noexcept(std::is_nothrow_move_constructible_v<std::decay_t<C>> &&
114 (std::is_nothrow_move_constructible_v<std::decay_t<Ts>> && ...))
115 requires(std::is_move_constructible_v<std::decay_t<C>> && (std::is_move_constructible_v<std::decay_t<Ts>> && ...))
116 {
117 return kumi::_::bind_t<kumi::_::Binding::front, std::decay_t<C>, std::decay_t<Ts>...>{KUMI_FWD(c), KUMI_FWD(ts)...};
118 }
119 }
120