mimic++ v9.2.1
Loading...
Searching...
No Matches
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
16
17#ifndef MIMICPP_DETAIL_IS_MODULE
18 #include <concepts>
19 #include <cstddef>
20 // ReSharper disable once CppUnusedIncludeDirective
21 #include <functional> // std::invoke
22 #include <tuple>
23 #include <type_traits>
24 #include <utility>
25#endif
26
28{
29 template <typename Matcher>
31 {
32 public:
33 Matcher const& matcher;
34
35 template <typename... Args>
36 requires std::invocable<detail::matches_hook::matches_fn, Matcher const&, Args&...>
37 [[nodiscard]]
38 // projected arguments may come as value, so Args& won't work in all cases
39 // just forward them as lvalue-ref
40 constexpr bool operator()(Args&&... args) const
41 noexcept(
42 std::is_nothrow_invocable_v<
43 decltype(detail::matches_hook::matches),
44 Matcher const&,
45 Args&...>)
46 {
47 return detail::matches_hook::matches(matcher, args...);
48 }
49 };
50
51 template <typename Matcher, typename MatchesStrategy, typename DescribeStrategy>
53 {
54 public:
55 [[nodiscard]]
56 explicit constexpr ArgsRequirement(
57 Matcher matcher,
58 MatchesStrategy matchesStrategy,
59 DescribeStrategy describeStrategy)
60 noexcept(
61 std::is_nothrow_move_constructible_v<Matcher>
62 && std::is_nothrow_move_constructible_v<MatchesStrategy>
63 && std::is_nothrow_move_constructible_v<DescribeStrategy>)
64 : m_Matcher{std::move(matcher)},
65 m_MatchesStrategy{std::move(matchesStrategy)},
66 m_DescribeStrategy{std::move(describeStrategy)}
67 {
68 }
69
70 [[nodiscard]]
71 static constexpr bool is_satisfied() noexcept
72 {
73 return true;
74 }
75
76 template <typename Return, typename... Args>
77 requires std::is_invocable_r_v<bool, MatchesStrategy const&, matcher_matches_fn<Matcher>, call::Info<Return, Args...> const&>
78 [[nodiscard]]
79 constexpr bool matches(const call::Info<Return, Args...>& info) const
80 noexcept(std::is_nothrow_invocable_v<MatchesStrategy const&, matcher_matches_fn<Matcher>, call::Info<Return, Args...> const&>)
81 {
82 return std::invoke(
83 m_MatchesStrategy,
85 info);
86 }
87
88 template <typename Return, typename... Args>
89 static constexpr void consume([[maybe_unused]] call::Info<Return, Args...> const& info) noexcept
90 {
91 }
92
93 [[nodiscard]]
94 std::optional<StringT> describe() const
95 {
96 [[maybe_unused]] auto const description = detail::describe_hook::describe(m_Matcher);
97
98 if constexpr (util::boolean_testable<decltype(description)>)
99 {
100 if (description)
101 {
102 return std::invoke(m_DescribeStrategy, *description);
103 }
104
105 return std::nullopt;
106 }
107 else if constexpr (std::convertible_to<decltype(description), StringViewT>)
108 {
109 return std::invoke(m_DescribeStrategy, description);
110 }
111 else
112 {
113 return std::nullopt;
114 }
115 }
116
117 private:
118 Matcher m_Matcher;
119 [[no_unique_address]] MatchesStrategy m_MatchesStrategy;
120 [[no_unique_address]] DescribeStrategy m_DescribeStrategy;
121 };
122}
123
124namespace mimicpp::expect::detail
125{
126 template <std::size_t index, std::size_t... others>
127 struct arg_requirement_describer
128 {
129 [[nodiscard]]
130 StringT operator()(StringViewT const matcherDescription) const
131 {
132 StringStreamT out{};
133 out << "expect: arg[" << index;
134 ((out << ", " << others), ...);
135 out << "] " << matcherDescription;
136 return std::move(out).str();
137 }
138 };
139
140 struct all_args_requirement_describer
141 {
142 [[nodiscard]]
143 StringT operator()(StringViewT const matcherDescription) const
144 {
145 StringStreamT out{};
146 out << "expect: arg[all] " << matcherDescription;
147 return std::move(out).str();
148 }
149 };
150
151 template <
152 std::size_t... indices,
153 typename Matcher,
154 typename... Projections>
155 [[nodiscard]]
156 constexpr auto make_args_policy(
157 Matcher&& matcher,
158 std::tuple<Projections...>&& projections)
159 {
160 static_assert(
161 sizeof...(indices) == sizeof...(Projections),
162 "Indices and projections size mismatch.");
163
164 using arg_selector_t = mimicpp::detail::args_selector_fn<
165 std::add_lvalue_reference_t,
166 std::index_sequence<indices...>>;
167 using apply_strategy_t = mimicpp::detail::arg_list_indirect_apply_fn<std::remove_cvref_t<Projections>...>;
168 using describe_strategy_t = arg_requirement_describer<indices...>;
169
171 std::forward<Matcher>(matcher),
172 mimicpp::detail::apply_args_fn(
173 arg_selector_t{},
174 apply_strategy_t{std::move(projections)}),
175 describe_strategy_t{}};
176 }
177}
178
180{
191
205 template <std::size_t index, typename Matcher, typename Projection = std::identity>
206 [[nodiscard]]
207 constexpr auto arg(
208 Matcher&& matcher,
209 Projection&& projection = {})
210 noexcept(
211 std::is_nothrow_constructible_v<std::remove_cvref_t<Matcher>, Matcher>
212 && std::is_nothrow_constructible_v<std::remove_cvref_t<Projection>, Projection>)
213 {
214 return detail::make_args_policy<index>(
215 std::forward<Matcher>(matcher),
216 std::forward_as_tuple(std::forward<Projection>(projection)));
217 }
218
240 template <
241 std::size_t first,
242 std::size_t... others,
243 typename Matcher,
244 typename... Projections>
245 [[nodiscard]]
246 constexpr auto args(Matcher&& matcher, Projections&&... projections)
247 noexcept(
248 std::is_nothrow_constructible_v<std::remove_cvref_t<Matcher>, Matcher>
249 && (... && std::is_nothrow_move_constructible_v<std::remove_cvref_t<Projections>>))
250 {
251 static_assert(
252 sizeof...(projections) <= 1u + sizeof...(others),
253 "The projection count exceeds the amount of indices.");
254
255 return detail::make_args_policy<first, others...>(
256 std::forward<Matcher>(matcher),
257 util::detail::expand_tuple<std::identity, 1u + sizeof...(others)>(
258 std::forward_as_tuple(std::forward<Projections>(projections)...)));
259 }
260
273 template <typename Matcher>
274 [[nodiscard]]
275 constexpr auto all_args(Matcher&& matcher)
276 noexcept(std::is_nothrow_constructible_v<std::remove_cvref_t<Matcher>, Matcher>)
277 {
278 using arg_selector_t = mimicpp::detail::all_args_selector_fn<std::add_lvalue_reference_t>;
279 using apply_strategy_t = mimicpp::detail::arg_list_forward_apply_fn;
280 using describe_strategy_t = detail::all_args_requirement_describer;
281
283 std::forward<Matcher>(matcher),
284 mimicpp::detail::apply_args_fn(
285 arg_selector_t{},
286 apply_strategy_t{}),
287 describe_strategy_t{}};
288 }
289
293}
294
295#endif
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Definition Call.hpp:27
Definition ArgRequirementPolicies.hpp:53
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:56
constexpr bool matches(const call::Info< Return, Args... > &info) const noexcept(std::is_nothrow_invocable_v< MatchesStrategy const &, matcher_matches_fn< Matcher >, call::Info< Return, Args... > const & >)
Definition ArgRequirementPolicies.hpp:79
static constexpr void consume(call::Info< Return, Args... > const &info) noexcept
Definition ArgRequirementPolicies.hpp:89
std::optional< StringT > describe() const
Definition ArgRequirementPolicies.hpp:94
static constexpr bool is_satisfied() noexcept
Definition ArgRequirementPolicies.hpp:71
Determines, whether B behaves as a the builtin type bool.
Definition Concepts.hpp:66
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:207
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:275
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:246
Definition ArgRequirementPolicies.hpp:125
Definition ArgRequirementPolicies.hpp:28
std::basic_ostringstream< CharT, CharTraitsT > StringStreamT
Definition Format.hpp:35
std::basic_string_view< CharT, CharTraitsT > StringViewT
Definition Fwd.hpp:392
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:391
Definition ArgRequirementPolicies.hpp:31
Matcher const & matcher
Definition ArgRequirementPolicies.hpp:33
constexpr bool operator()(Args &&... args) const noexcept(std::is_nothrow_invocable_v< decltype(detail::matches_hook::matches), Matcher const &, Args &... >)
Definition ArgRequirementPolicies.hpp:40