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