mimic++ v6
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
ArgRequirementPolicies.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_ARG_REQUIREMENT_POLICIES_HPP
7#define MIMICPP_POLICIES_ARG_REQUIREMENT_POLICIES_HPP
8
9#pragma once
10
13
14#include <concepts>
15// ReSharper disable once CppUnusedIncludeDirective
16#include <functional> // std::invoke
17#include <tuple>
18#include <type_traits>
19#include <utility>
20
22{
23 template <typename Matcher>
25 {
26 public:
27 const Matcher& matcher;
28
29 template <typename... Args>
30 requires std::invocable<
31 decltype(detail::matches_hook::matches),
32 const Matcher&,
33 Args&...>
34 [[nodiscard]]
35 // projected arguments may come as value, so Args& won't work in all cases
36 // just forward them as lvalue-ref
37 constexpr bool operator()(Args&&... args) const
38 noexcept(
39 std::is_nothrow_invocable_v<
40 decltype(detail::matches_hook::matches),
41 const Matcher&,
42 Args&...>)
43 {
44 return detail::matches_hook::matches(matcher, args...);
45 }
46 };
47
48 template <typename Matcher, typename MatchesStrategy, typename DescribeStrategy>
50 {
51 public:
52 [[nodiscard]]
53 explicit constexpr ArgsRequirement(
54 Matcher matcher,
55 MatchesStrategy matchesStrategy,
56 DescribeStrategy describeStrategy)
57 noexcept(
58 std::is_nothrow_move_constructible_v<Matcher>
59 && std::is_nothrow_move_constructible_v<MatchesStrategy>
60 && std::is_nothrow_move_constructible_v<DescribeStrategy>)
61 : m_Matcher{std::move(matcher)},
62 m_MatchesStrategy{std::move(matchesStrategy)},
63 m_DescribeStrategy{std::move(describeStrategy)}
64 {
65 }
66
67 [[nodiscard]]
68 static constexpr bool is_satisfied() noexcept
69 {
70 return true;
71 }
72
73 template <typename Return, typename... Args>
74 requires std::is_invocable_r_v<bool, const MatchesStrategy&, matcher_matches_fn<Matcher>, const call::Info<Return, Args...>&>
75 [[nodiscard]]
76 constexpr bool matches(const call::Info<Return, Args...>& info) const
77 noexcept(std::is_nothrow_invocable_v<const MatchesStrategy&, matcher_matches_fn<Matcher>, const call::Info<Return, Args...>&>)
78 {
79 return std::invoke(
80 m_MatchesStrategy,
82 info);
83 }
84
85 template <typename Return, typename... Args>
86 static constexpr void consume([[maybe_unused]] const call::Info<Return, Args...>& info) noexcept
87 {
88 }
89
90 [[nodiscard]]
92 {
93 return std::invoke(
94 m_DescribeStrategy,
95 detail::describe_hook::describe(m_Matcher));
96 }
97
98 private:
99 Matcher m_Matcher;
100 [[no_unique_address]] MatchesStrategy m_MatchesStrategy;
101 [[no_unique_address]] DescribeStrategy m_DescribeStrategy;
102 };
103}
104
106{
107 namespace detail
108 {
109 template <std::size_t index, std::size_t... others>
110 struct arg_requirement_describer
111 {
112 [[nodiscard]]
113 StringT operator()(const StringViewT matcherDescription) const
114 {
115 StringStreamT out{};
116 out << "expect: arg[" << index;
117 ((out << ", " << others), ...);
118 out << "] " << matcherDescription;
119 return std::move(out).str();
120 }
121 };
122
123 struct all_args_requirement_describer
124 {
125 [[nodiscard]]
126 StringT operator()(const StringViewT matcherDescription) const
127 {
128 StringStreamT out{};
129 out << "expect: arg[all] " << matcherDescription;
130 return std::move(out).str();
131 }
132 };
133
134 template <
135 std::size_t... indices,
136 typename Matcher,
137 typename... Projections>
138 [[nodiscard]]
139 constexpr auto make_args_policy(
140 Matcher&& matcher,
141 std::tuple<Projections...>&& projections)
142 {
143 static_assert(
144 sizeof...(indices) == sizeof...(Projections),
145 "Indices and projections size mismatch.");
146
147 using arg_selector_t = mimicpp::detail::args_selector_fn<
148 std::add_lvalue_reference_t,
149 std::index_sequence<indices...>>;
150 using apply_strategy_t = mimicpp::detail::arg_list_indirect_apply_fn<std::remove_cvref_t<Projections>...>;
151 using describe_strategy_t = arg_requirement_describer<indices...>;
152
154 std::forward<Matcher>(matcher),
155 mimicpp::detail::apply_args_fn(
156 arg_selector_t{},
157 apply_strategy_t{std::move(projections)}),
158 describe_strategy_t{}};
159 }
160 }
161
172
186 template <std::size_t index, typename Matcher, typename Projection = std::identity>
187 [[nodiscard]]
188 constexpr auto arg(
189 Matcher&& matcher,
190 Projection&& projection = {})
191 noexcept(
192 std::is_nothrow_constructible_v<std::remove_cvref_t<Matcher>, Matcher>
193 && std::is_nothrow_constructible_v<std::remove_cvref_t<Projection>, Projection>)
194 {
195 return detail::make_args_policy<index>(
196 std::forward<Matcher>(matcher),
197 std::forward_as_tuple(std::forward<Projection>(projection)));
198 }
199
221 template <
222 std::size_t first,
223 std::size_t... others,
224 typename Matcher,
225 typename... Projections>
226 [[nodiscard]]
227 constexpr auto args(Matcher&& matcher, Projections&&... projections)
228 noexcept(
229 std::is_nothrow_constructible_v<std::remove_cvref_t<Matcher>, Matcher>
230 && (... && std::is_nothrow_move_constructible_v<std::remove_cvref_t<Projections>>))
231 {
232 static_assert(
233 sizeof...(projections) <= 1u + sizeof...(others),
234 "The projection count exceeds the amount of indices.");
235
236 return detail::make_args_policy<first, others...>(
237 std::forward<Matcher>(matcher),
238 mimicpp::detail::expand_tuple<std::identity, 1u + sizeof...(others)>(
239 std::forward_as_tuple(std::forward<Projections>(projections)...)));
240 }
241
254 template <typename Matcher>
255 [[nodiscard]]
256 constexpr auto all_args(Matcher&& matcher)
257 noexcept(std::is_nothrow_constructible_v<std::remove_cvref_t<Matcher>, Matcher>)
258 {
259 using arg_selector_t = mimicpp::detail::all_args_selector_fn<std::add_lvalue_reference_t>;
260 using apply_strategy_t = mimicpp::detail::arg_list_forward_apply_fn;
261 using describe_strategy_t = detail::all_args_requirement_describer;
262
264 std::forward<Matcher>(matcher),
265 mimicpp::detail::apply_args_fn(
266 arg_selector_t{},
267 apply_strategy_t{}),
268 describe_strategy_t{}};
269 }
270
274}
275
276#endif
Definition Fwd.hpp:19
Definition ArgRequirementPolicies.hpp:50
static constexpr void consume(const call::Info< Return, Args... > &info) noexcept
Definition ArgRequirementPolicies.hpp:86
constexpr ArgsRequirement(Matcher matcher, MatchesStrategy matchesStrategy, DescribeStrategy describeStrategy) noexcept(std::is_nothrow_move_constructible_v< Matcher > &&std::is_nothrow_move_constructible_v< MatchesStrategy > &&std::is_nothrow_move_constructible_v< DescribeStrategy >)
Definition ArgRequirementPolicies.hpp:53
StringT describe() const
Definition ArgRequirementPolicies.hpp:91
static constexpr bool is_satisfied() noexcept
Definition ArgRequirementPolicies.hpp:68
constexpr bool matches(const call::Info< Return, Args... > &info) const noexcept(std::is_nothrow_invocable_v< const MatchesStrategy &, matcher_matches_fn< Matcher >, const call::Info< Return, Args... > & >)
Definition ArgRequirementPolicies.hpp:76
constexpr auto arg(Matcher &&matcher, Projection &&projection={}) noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Matcher >, Matcher > &&std::is_nothrow_constructible_v< std::remove_cvref_t< Projection >, Projection >)
Checks whether the selected argument satisfies the given matcher.
Definition ArgRequirementPolicies.hpp:188
constexpr auto all_args(Matcher &&matcher) noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Matcher >, Matcher >)
Checks whether the all arguments satisfy the given matcher.
Definition ArgRequirementPolicies.hpp:256
constexpr auto args(Matcher &&matcher, Projections &&... projections) noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Matcher >, Matcher > &&(... &&std::is_nothrow_move_constructible_v< std::remove_cvref_t< Projections > >))
Checks whether the selected arguments satisfy the given matcher.
Definition ArgRequirementPolicies.hpp:227
Definition ArgRequirementPolicies.hpp:106
Definition ArgRequirementPolicies.hpp:22
std::basic_ostringstream< CharT, CharTraitsT > StringStreamT
Definition Printer.hpp:41
std::basic_string_view< CharT, CharTraitsT > StringViewT
Definition Fwd.hpp:345
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:344
Definition ArgRequirementPolicies.hpp:25
const Matcher & matcher
Definition ArgRequirementPolicies.hpp:27