Simple-Utility v2.3.1
Loading...
Searching...
No Matches
bind_back.hpp
Go to the documentation of this file.
1// Copyright Dominic Koepke 2019 - 2023.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// https://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef SL_UTILITY_FUNCTIONAL_BIND_BACK_HPP
7#define SL_UTILITY_FUNCTIONAL_BIND_BACK_HPP
8
9#pragma once
10
12
13#include <concepts>
14#include <functional>
15#include <tuple>
16#include <type_traits>
17#include <utility>
18
19namespace sl::functional::detail
20{
21 template <class Fn, class BoundArgsTuple, class... CallArgs>
22 constexpr decltype(auto) call_bind_back(Fn&& func, BoundArgsTuple&& boundArgsTuple, CallArgs&&... callArgs)
23 {
24 return std::apply(
25 [&]<class... TArgs>(TArgs&&... boundArgs) -> decltype(auto)
26 {
27 return std::invoke(
28 std::forward<Fn>(func),
29 std::forward<CallArgs>(callArgs)...,
30 std::forward<TArgs>(boundArgs)...);
31 },
32 std::forward<BoundArgsTuple>(boundArgsTuple));
33 }
34
35 template <class Fn, class... BoundArgs>
36 class BindBack
37 {
38 public:
39 template <class FnCTorArg, class... CTorArgs>
40 requires (sizeof...(CTorArgs) != 0 && !std::derived_from<std::remove_cvref_t<FnCTorArg>, BindBack>)
41 explicit constexpr BindBack(FnCTorArg&& fn, CTorArgs&&... ctorArgs)
42 : m_Fn{std::forward<FnCTorArg>(fn)},
43 m_BoundArgs{std::forward<CTorArgs>(ctorArgs)...}
44 {
45 }
46
47 template <class... CallArgs>
48 requires std::invocable<const Fn&, CallArgs..., const BoundArgs&...>
49 constexpr decltype(auto) operator()(
50 CallArgs&&... callArgs
51 ) const & noexcept(std::is_nothrow_invocable_v<const Fn&, CallArgs..., const BoundArgs&...>)
52 {
53 return call_bind_back(m_Fn, m_BoundArgs, std::forward<CallArgs>(callArgs)...);
54 }
55
56 template <class... CallArgs>
57 requires std::invocable<Fn&, CallArgs..., BoundArgs&...>
58 constexpr decltype(auto) operator()(
59 CallArgs&&... callArgs
60 ) & noexcept(std::is_nothrow_invocable_v<Fn&, CallArgs..., BoundArgs&...>)
61 {
62 return call_bind_back(m_Fn, m_BoundArgs, std::forward<CallArgs>(callArgs)...);
63 }
64
65 template <class... CallArgs>
66 requires std::invocable<const Fn&&, CallArgs..., const BoundArgs&&...>
67 constexpr decltype(auto) operator()(
68 CallArgs&&... callArgs
69 ) const && noexcept(std::is_nothrow_invocable_v<const Fn&&, CallArgs..., const BoundArgs&&...>)
70 {
71 return call_bind_back(std::move(m_Fn), std::move(m_BoundArgs), std::forward<CallArgs>(callArgs)...);
72 }
73
74 template <class... CallArgs>
75 requires std::invocable<Fn&&, CallArgs..., BoundArgs&&...>
76 constexpr decltype(auto) operator()(
77 CallArgs&&... callArgs
78 ) && noexcept(std::is_nothrow_invocable_v<Fn&&, CallArgs..., BoundArgs&&...>)
79 {
80 return call_bind_back(std::move(m_Fn), std::move(m_BoundArgs), std::forward<CallArgs>(callArgs)...);
81 }
82
83 private:
85 Fn m_Fn{};
86 std::tuple<BoundArgs...> m_BoundArgs{};
87 };
88
89 template <class TFunc, class... TBoundArgs>
90 BindBack(TFunc, TBoundArgs...) -> BindBack<TFunc, std::unwrap_ref_decay_t<TBoundArgs>...>;
91}
92
93namespace sl::functional
94{
100 inline constexpr auto bind_back = []<class Fn, class... BoundArgs>(
101 Fn&& func,
102 BoundArgs&&... boundArgs
103 ) noexcept(std::is_nothrow_constructible_v<std::remove_cvref_t<Fn>, Fn>
104 && (... && std::is_nothrow_constructible_v<std::unwrap_ref_decay_t<BoundArgs>, BoundArgs>))
105 {
106 return detail::BindBack{std::forward<Fn>(func), std::forward<BoundArgs>(boundArgs)...};
107 };
108}
109
110#endif
#define SL_UTILITY_NO_UNIQUE_ADDRESS
Definition: Config.hpp:21
constexpr auto bind_back
Helper function, which generates a forwarding call wrapper for the given function and curries the par...
Definition: bind_back.hpp:100
Definition: Arithmetic.hpp:13