tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
bind_front.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2021 Tobias Hienzsch
3
4#ifndef TETL_FUNCTIONAL_BIND_FRONT_HPP
5#define TETL_FUNCTIONAL_BIND_FRONT_HPP
6
7#include <etl/_functional/invoke.hpp>
8#include <etl/_tuple/apply.hpp>
9#include <etl/_tuple/tuple.hpp>
10#include <etl/_type_traits/decay.hpp>
11#include <etl/_type_traits/invoke_result.hpp>
12#include <etl/_type_traits/is_base_of.hpp>
13#include <etl/_type_traits/unwrap_reference.hpp>
14#include <etl/_utility/forward.hpp>
15#include <etl/_utility/move.hpp>
16
17namespace etl {
18
19namespace detail {
20
21template <typename Func, typename BoundArgsTuple, typename... CallArgs>
22constexpr auto bind_front_caller(Func&& func, BoundArgsTuple&& boundArgsTuple, CallArgs&&... callArgs) -> decltype(auto)
23{
24 return etl::apply([&func, &callArgs...]<typename... BoundArgs>(BoundArgs&&... boundArgs) -> decltype(auto) {
25 return etl::invoke(
26 etl::forward<Func>(func),
27 etl::forward<BoundArgs>(boundArgs)...,
28 etl::forward<CallArgs>(callArgs)...
29 );
30 }, etl::forward<BoundArgsTuple>(boundArgsTuple));
31}
32
33template <typename Func, typename... BoundArgs>
34class bind_front_t {
35public:
36 template <typename F, typename... BA>
37 requires(!(sizeof...(BA) == 0 && is_base_of_v<bind_front_t, decay_t<F>>))
38 explicit bind_front_t(F&& f, BA&&... ba)
39 : _func(etl::forward<F>(f))
40 , _boundArgs(etl::forward<BA>(ba)...)
41 {
42 }
43
44 // TODO: Add noexcept(is_nothrow_invocable_v<Func&, BoundArgs&..., CallArgs...>)
45 template <typename... CallArgs>
46 auto operator()(CallArgs&&... callArgs) & -> invoke_result_t<Func&, BoundArgs&..., CallArgs...>
47 {
48 return bind_front_caller(_func, _boundArgs, etl::forward<CallArgs>(callArgs)...);
49 }
50
51 // TODO: Add noexcept(is_nothrow_invocable_v<Func const&, BoundArgs const&...,CallArgs...>)
52 template <typename... CallArgs>
53 auto operator()(CallArgs&&... callArgs) const& -> invoke_result_t<Func const&, BoundArgs const&..., CallArgs...>
54 {
55 return bind_front_caller(_func, _boundArgs, etl::forward<CallArgs>(callArgs)...);
56 }
57
58 // TODO: Add noexcept(is_nothrow_invocable_v<Func, BoundArgs..., CallArgs...>)
59 template <typename... CallArgs>
60 auto operator()(CallArgs&&... callArgs) && -> invoke_result_t<Func, BoundArgs..., CallArgs...>
61 {
62 return bind_front_caller(etl::move(_func), etl::move(_boundArgs), etl::forward<CallArgs>(callArgs)...);
63 }
64
65 // TODO: noexcept(is_nothrow_invocable_v<Func const, BoundArgs const...,CallArgs...>)
66 template <typename... CallArgs>
67 auto operator()(CallArgs&&... callArgs) const&& -> invoke_result_t<Func const, BoundArgs const..., CallArgs...>
68 {
69 return bind_front_caller(etl::move(_func), etl::move(_boundArgs), etl::forward<CallArgs>(callArgs)...);
70 }
71
72private:
73 Func _func;
74 tuple<BoundArgs...> _boundArgs;
75};
76
77} // namespace detail
78
79/// \brief The function template bind_front generates a forwarding call wrapper
80/// for f. Calling this wrapper is equivalent to invoking f with its first
81/// sizeof...(Args) parameters bound to args. In other words, bind_front(f,
82/// bound_args...)(call_args...) is equivalent to invoke(f, bound_args...,
83/// call_args....).
84///
85/// \details Copied implementation from paper:
86/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0356r5.html
87template <typename Func, typename... BoundArgs>
88constexpr auto bind_front(Func&& func, BoundArgs&&... boundArgs)
89{
90 return detail::bind_front_t<decay_t<Func>, unwrap_ref_decay_t<BoundArgs>...>{
91 etl::forward<Func>(func),
92 etl::forward<BoundArgs>(boundArgs)...
93 };
94}
95
96} // namespace etl
97
98#endif // TETL_FUNCTIONAL_BIND_FRONT_HPP
Definition adjacent_find.hpp:9
constexpr auto bind_front(Func &&func, BoundArgs &&... boundArgs)
The function template bind_front generates a forwarding call wrapper for f. Calling this wrapper is e...
Definition bind_front.hpp:88
Definition tuple.hpp:114