mimic++ v9.2.1
Loading...
Searching...
No Matches
ArgumentList.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2024 - 2025.
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 MIMICPP_POLICIES_ARGUMENT_LIST_HPP
7#define MIMICPP_POLICIES_ARGUMENT_LIST_HPP
8
9#pragma once
10
11#include "mimic++/Call.hpp"
13
14#ifndef MIMICPP_DETAIL_IS_MODULE
15 #include <concepts>
16 // ReSharper disable once CppUnusedIncludeDirective
17 #include <functional> // std::invoke
18 #include <tuple>
19 #include <type_traits>
20 #include <utility>
21#endif
22
23namespace mimicpp::detail
24{
25 template <typename ArgSelector, typename ApplyStrategy>
26 struct apply_args_fn
27 {
28 public:
29 [[nodiscard]]
30 explicit constexpr apply_args_fn(ArgSelector argSelector, ApplyStrategy applyStrategy)
31 noexcept(
32 std::is_nothrow_move_constructible_v<ArgSelector>
33 && std::is_nothrow_move_constructible_v<ApplyStrategy>)
34 : m_ArgSelector{std::move(argSelector)},
35 m_ApplyStrategy{std::move(applyStrategy)}
36 {
37 }
38
39 template <typename Action, typename Return, typename... Args>
40 requires std::invocable<const ArgSelector&, const call::Info<Return, Args...>&>
41 && std::invocable<
42 const ApplyStrategy&,
43 Action,
44 std::invoke_result_t<const ArgSelector&, const call::Info<Return, Args...>&>>
45 constexpr decltype(auto) operator()(Action&& action, const call::Info<Return, Args...>& info) const
46 noexcept(
47 std::is_nothrow_invocable_v<const ArgSelector&, const call::Info<Return, Args...>&>
48 && std::is_nothrow_invocable_v<
49 const ApplyStrategy&,
50 Action,
51 std::invoke_result_t<const ArgSelector&, const call::Info<Return, Args...>&>>)
52 {
53 return std::invoke(
54 m_ApplyStrategy,
55 std::forward<Action>(action),
56 std::invoke(m_ArgSelector, info));
57 }
58
59 private:
60 ArgSelector m_ArgSelector;
61 ApplyStrategy m_ApplyStrategy;
62 };
63
64 template <template <typename> typename TypeProjection, typename IndexSequence>
65 struct args_selector_fn;
66
67 template <template <typename> typename TypeProjection, std::size_t... indices>
68 struct args_selector_fn<TypeProjection, std::index_sequence<indices...>>
69 {
70 public:
71 static_assert(
72 std::is_reference_v<TypeProjection<int&>>,
73 "Only use reference-projections.");
74
75 template <std::size_t index, typename Signature>
76 using projected_t = TypeProjection<signature_param_type_t<index, Signature>>;
77
78 template <typename Return, typename... Args>
79 constexpr auto operator()(const call::Info<Return, Args...>& callInfo) const noexcept
80 {
81 using signature_t = Return(Args...);
82
83 return std::forward_as_tuple(
84 static_cast<projected_t<indices, signature_t>>(
85 // all elements are std::reference_wrapper, so unwrap them first
86 std::get<indices>(callInfo.args).get())...);
87 }
88 };
89
90 template <template <typename> typename TypeProjection>
91 struct all_args_selector_fn
92 {
93 public:
94 template <typename Return, typename... Args>
95 constexpr auto operator()(const call::Info<Return, Args...>& callInfo) const noexcept
96 {
97 return std::invoke(
98 args_selector_fn<TypeProjection, std::index_sequence_for<Args...>>{},
99 callInfo);
100 }
101 };
102
103 struct arg_list_forward_apply_fn
104 {
105 public:
106 template <typename Fun, typename... Args>
107 requires std::invocable<Fun, Args...>
108 constexpr decltype(auto) operator()(Fun&& fun, std::tuple<Args...>&& argList) const
109 noexcept(std::is_nothrow_invocable_v<Fun, Args...>)
110 {
111 return std::apply(
112 std::forward<Fun>(fun),
113 std::move(argList));
114 }
115 };
116
117 template <typename... Projections>
118 struct arg_list_indirect_apply_fn
119 {
120 public:
121 [[nodiscard]]
122 explicit constexpr arg_list_indirect_apply_fn(std::tuple<Projections...> projections = {})
123 noexcept(std::is_nothrow_move_constructible_v<std::tuple<Projections...>>)
124 : m_Projections{std::move(projections)}
125 {
126 }
127
128 template <typename Fun, typename... Args>
129 requires(... && std::invocable<const Projections&, Args>)
130 && std::invocable<Fun, std::invoke_result_t<const Projections&, Args>...>
131 constexpr decltype(auto) operator()(Fun&& fun, std::tuple<Args...>&& argList) const
132 noexcept(
133 (... && std::is_nothrow_invocable_v<const Projections&, Args>)
134 && std::is_nothrow_invocable_v<Fun, std::invoke_result_t<const Projections&, Args>...>)
135 {
136 return invoke_impl(
137 std::forward<Fun>(fun),
138 std::move(argList),
139 std::index_sequence_for<Projections...>{});
140 }
141
142 private:
143 std::tuple<Projections...> m_Projections;
144
145 template <typename Fun, typename... Args, std::size_t... indices>
146 constexpr decltype(auto) invoke_impl(
147 Fun&& fun,
148 std::tuple<Args...>&& argList,
149 [[maybe_unused]] const std::index_sequence<indices...>) const
150 {
151 return std::invoke(
152 std::forward<Fun>(fun),
153 std::invoke(
154 std::get<indices>(m_Projections),
155 std::forward<Args>(std::get<indices>(argList)))...);
156 }
157 };
158}
159
160#endif