Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
bind_front.hpp
Go to the documentation of this file.
1// parasoft-suppress ALL "False Positive: there is no executable code on line 1"
2// parasoft-begin-suppress AUTOSAR-A2_8_1-a-2 "False positive: also defines arene::base::bind_front"
3
4// Copyright 2026, Toyota Motor Corporation
5//
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
8#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_FUNCTIONAL_BIND_FRONT_HPP_
9#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_FUNCTIONAL_BIND_FRONT_HPP_
10
11// IWYU pragma: private, include "arene/base/functional.hpp"
12// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
13
14// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
15#include "arene/base/compiler_support/cpp14_inline.hpp"
16#include "arene/base/functional/invoke.hpp"
17#include "arene/base/functional/perfect_forward_call_wrapper.hpp"
18#include "arene/base/stdlib_choice/cstddef.hpp"
19#include "arene/base/stdlib_choice/decay.hpp"
20#include "arene/base/stdlib_choice/forward.hpp"
21#include "arene/base/stdlib_choice/integer_sequence.hpp"
22#include "arene/base/stdlib_choice/is_constructible.hpp"
23#include "arene/base/stdlib_choice/is_move_constructible.hpp"
24#include "arene/base/stdlib_choice/tuple.hpp"
25#include "arene/base/type_traits/all_of.hpp"
26// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
27
28namespace arene {
29namespace base {
30
31namespace bind_front_detail {
32
33/// @brief Forward declaration to allow specialization
34/// @tparam NBound The number of bound arguments.
35/// @tparam Indexes A @c std::index_sequence of size @c NBound .
36template <std::size_t NBound, typename Indexes = std::make_index_sequence<NBound>>
37class bind_front_policy;
38
39/// @brief Implementation helper for @c arene::base::bind_front intended to be used as a policy for
40/// @c arene::base::functional_detail::perfect_forwarding_call_wrapper .
41///
42/// @tparam NBound The number of bound arguments.
43/// @tparam Is The set of indexes of the bound arguments in the BoundArgs tuple .
44template <std::size_t NBound, std::size_t... Is>
45class bind_front_policy<NBound, std::index_sequence<Is...>> {
46 public:
47 /// @brief Invokes the provided function as expression-equivalent to @c func(bound_args...,call_args...) .
48 ///
49 /// @tparam FuncT The type of the callable to invoke.
50 /// @tparam BoundArgsTupleT The type of a tuple holding the bound arguments.
51 /// @tparam CallArgsT The types of the call arguments to invoke the callable with.
52 /// @param func The invocable to invoke.
53 /// @param bound_args A tuple of bound arguments to pass to the invocable.
54 /// @param call_args The set of call arguments to pass to the invocable.
55 /// @return The return from invoking the held callable with the bound and call arguments.
56 template <typename FuncT, typename BoundArgsTupleT, typename... CallArgsT>
57 constexpr auto operator()(FuncT&& func, BoundArgsTupleT&& bound_args, CallArgsT&&... call_args) const
58 noexcept((noexcept(::arene::base::invoke(
59 std::forward<FuncT>(func),
60 std::get<Is>(std::forward<BoundArgsTupleT>(bound_args))...,
61 std::forward<CallArgsT>(call_args)...
62 ))))
63 -> decltype(::arene::base::invoke(
64 std::forward<FuncT>(func),
65 std::get<Is>(std::forward<BoundArgsTupleT>(bound_args))...,
66 std::forward<CallArgsT>(call_args)...
67 )) {
68 return ::arene::base::invoke(
69 std::forward<FuncT>(func),
70 std::get<Is>(std::forward<BoundArgsTupleT>(bound_args))...,
71 std::forward<CallArgsT>(call_args)...
72 );
73 }
74};
75
76/// @brief Simplifies correctly setting up the call wrapper and policy
77///
78/// @tparam BoundFunc The type of the function to bind, post decaying.
79/// @tparam BoundArgs The type of the arguments to bind, post decaying.
80/// @note This needs to be a struct rather than just a type alias or else gcc crashes on all versions between 8 and 12.
81template <typename BoundFunc, typename... BoundArgs>
82class bind_front_t
83 : functional_detail::
84 perfect_forward_call_wrapper<bind_front_policy<sizeof...(BoundArgs)>, BoundFunc, BoundArgs...> {
85 /// @brief specialization of perfect_forward_call_wrapper that binds arguments to the front
86 using impl_type =
87 functional_detail::perfect_forward_call_wrapper<bind_front_policy<sizeof...(BoundArgs)>, BoundFunc, BoundArgs...>;
88
89 public:
90 using impl_type::impl_type;
91 using impl_type::operator();
92};
93
94/// @brief function object implementing bind_front
95class bind_front_fn {
96 public:
97 /// @brief Produces a call wrapper which allows invoking an input callable with its first N arguments bound to @c args
98 /// .
99 ///
100 /// @tparam BoundFunc The type of the callable to create a wrapper for. Must satisfy
101 // @c std::is_constructible<std::decay_t<BoundFunc>,BoundFunc> and
102 // @c std::is_move_constructible<std::decay_t<BoundFunc>> or else the program is ill-formed.
103 /// @tparam BoundArgs The types of the arguments to bind to the callable. Must satisfy
104 // @c std::is_constructible<std::tuple<std::decay_t<BoundArgs>...>, BoundArgs&&...> and
105 // @c std::is_move_constructible<std::tuple<std::decay_t<BoundArgs>...>> or else the program is ill-formed.
106 /// @param bound_func The callable to create a wrapper for. It will be perfect-forwarded into the call wrapper.
107 /// @param bound_args The set of arguments to bind to the callable. They will be perfect-forwarded into the call
108 /// wrapper.
109 /// @return An implementation defined callable object, whose call operator can consume a set of arguments @c call_args
110 /// .
111 /// <c> bind_front(bound_func, bound_args...)(call_args...) </c> is expression-equivalent to
112 /// <c> invoke(bound_func, bound_args..., call_args...) </c> . The @c noexcept -ness of @c bound_func is
113 /// preserved by the call operator of the returned object.
114 ///
115 /// The wrapper perfect forwards the input callable and binding arguments _into the wrapper_, otherwise temporaries
116 /// would always dangle, and references would be at high risk of dangling. When the returned callable is invoked, its
117 /// reference qualification is applied to the access of the bound objects. If @c g is the callable returned from @c
118 /// bind_front(f,args...) , then invoking @c std::move(g)(call_args...) will allow the bound arguments to be moved
119 /// into the bound callable. Similarly, if @c f where to have non-const lvalue parameters for at the position of bound
120 /// arguments, then invoking @c g(call_args..) when @c g is a non-const lvalue will result in the instances of the
121 /// bound arguments held in the wrapper being passed to @c f , similar to a @c mutable lambda with a capture block.
122 ///
123 /// If a caller wishes to maintain "reference semantics" of the bound arguments when it can be assured the lifetime of
124 /// the bound arguments will exceed the lifetime of the returned callable, this can be achieved by wrapping the
125 /// argument in @c std::reference_wrapper .
126 // parasoft-begin-suppress AUTOSAR-M3_3_2-a "False positive: static cannot be applied, this is not a member function."
127 // parasoft-begin-suppress CERT_C-EXP37-a "False positive: there is no function pointer decay/conversion."
128 template <typename BoundFunc, typename... BoundArgs>
129 constexpr auto operator()(BoundFunc&& bound_func, BoundArgs&&... bound_args) const noexcept(
130 std::is_nothrow_constructible<std::decay_t<BoundFunc>, BoundFunc>::value &&
131 std::is_nothrow_constructible<std::tuple<std::decay_t<BoundArgs>...>, BoundArgs&&...>::value
132 ) -> bind_front_detail::bind_front_t<std::decay_t<BoundFunc>, std::decay_t<BoundArgs>...> {
133 static_assert(
134 std::is_constructible<std::decay_t<BoundFunc>, BoundFunc&&>::value,
135 "Bound function must be constructible from input."
136 );
137 static_assert(
138 std::is_move_constructible<std::decay_t<BoundFunc>>::value,
139 "Bound function must be move-constructible."
140 );
141 static_assert(
142 ::arene::base::all_of_v<std::is_constructible<std::decay_t<BoundArgs>, BoundArgs&&>::value...>,
143 "Bound arguments must be capturable from input."
144 );
145 static_assert(
146 ::arene::base::all_of_v<std::is_move_constructible<std::decay_t<BoundArgs>>::value...>,
147 "Bound arguments must be move-constructible."
148 );
149 return bind_front_detail::bind_front_t<std::decay_t<BoundFunc>, std::decay_t<BoundArgs>...>{
150 std::forward<BoundFunc>(bound_func),
151 std::forward<BoundArgs>(bound_args)...,
152 };
153 }
154 // parasoft-end-suppress CERT_C-EXP37-a
155 // parasoft-end-suppress AUTOSAR-M3_3_2-a "False positive: static cannot be applied, this is not a member function."
156};
157
158} // namespace bind_front_detail
159
160/// @def arene::base::bind_front
161/// @copydoc arene::base::bind_front_detail::bind_front_fn::operator()
162// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
163// object used in multiple TUs."
164// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
165// object used in multiple TUs."
166ARENE_CPP14_INLINE_VARIABLE(bind_front_detail::bind_front_fn, bind_front);
167// parasoft-end-suppress AUTOSAR-M7_3_3-a
168// parasoft-end-suppress CERT_CPP-DCL59-a
169
170} // namespace base
171} // namespace arene
172
173// parasoft-end-suppress AUTOSAR-A2_8_1-a-2 "False positive: also defines arene::base::bind_front"
174
175#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_FUNCTIONAL_BIND_FRONT_HPP_
Definition array_exceptions_disabled.cpp:11
ARENE_CPP14_INLINE_VARIABLE(bind_front_detail::bind_front_fn, bind_front)
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10