mimic++ v9.2.1
Loading...
Searching...
No Matches
GeneralMatchers.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_MATCHERS_GENERAL_MATCHERS_HPP
7#define MIMICPP_MATCHERS_GENERAL_MATCHERS_HPP
8
9#pragma once
10
11#include "mimic++/Fwd.hpp"
18
19#ifndef MIMICPP_DETAIL_IS_MODULE
20 #include <functional>
21 #include <tuple>
22 #include <type_traits>
23 #include <utility>
24#endif
25
26namespace mimicpp::detail
27{
28 template <typename Arg, typename MatchesProjection = std::identity, typename DescribeProjection = printing::PrintFn>
29 struct arg_storage
30 {
31 using matches_reference = std::invoke_result_t<MatchesProjection, const Arg&>;
32 using describe_reference = std::invoke_result_t<DescribeProjection, const Arg&>;
33
34 Arg arg;
35
36 decltype(auto) as_matches_arg() const noexcept(std::is_nothrow_invocable_v<MatchesProjection, const Arg&>)
37 {
38 return std::invoke(MatchesProjection{}, arg);
39 }
40
41 decltype(auto) as_describe_arg() const noexcept(std::is_nothrow_invocable_v<DescribeProjection, const Arg&>)
42 {
43 return std::invoke(DescribeProjection{}, arg);
44 }
45 };
46
47 template <typename T>
48 struct to_arg_storage
49 {
50 using type = arg_storage<T>;
51 };
52
53 template <typename Arg, typename MatchesProjection, typename DescribeProjection>
54 struct to_arg_storage<arg_storage<Arg, MatchesProjection, DescribeProjection>>
55 {
56 using type = arg_storage<Arg, MatchesProjection, DescribeProjection>;
57 };
58
59 template <typename T>
60 using to_arg_storage_t = typename to_arg_storage<T>::type;
61}
62
64{
71 template <typename Predicate, typename... AdditionalArgs>
72 requires std::is_move_constructible_v<Predicate>
73 && (... && std::is_move_constructible_v<AdditionalArgs>)
75 {
76 private:
77 using storage_t = std::tuple<detail::to_arg_storage_t<AdditionalArgs>...>;
78 template <typename T>
79 using matches_reference_t = typename detail::to_arg_storage_t<T>::matches_reference;
80
81 public:
82 [[nodiscard]]
83 explicit constexpr PredicateMatcher(
84 Predicate predicate,
85 StringViewT fmt,
86 StringViewT invertedFmt,
87 std::tuple<AdditionalArgs...> additionalArgs = {})
88 noexcept(
89 std::is_nothrow_move_constructible_v<Predicate>
90 && (... && std::is_nothrow_move_constructible_v<AdditionalArgs>))
91 : m_Predicate{std::move(predicate)},
92 m_FormatString{std::move(fmt)},
93 m_InvertedFormatString{std::move(invertedFmt)},
94 m_AdditionalArgs{std::move(additionalArgs)}
95 {
96 }
97
98 template <typename First, typename... Others>
99 requires std::predicate<
100 const Predicate&,
101 First&,
102 Others&...,
103 matches_reference_t<AdditionalArgs>...>
104 [[nodiscard]]
105 constexpr bool matches(
106 First& first,
107 Others&... others) const
108 noexcept(
109 std::is_nothrow_invocable_v<
110 const Predicate&,
111 First&,
112 Others&...,
113 matches_reference_t<AdditionalArgs>...>)
114 {
115 return std::apply(
116 [&, this](auto&... additionalArgs) {
117 return std::invoke(
118 m_Predicate,
119 first,
120 others...,
121 additionalArgs.as_matches_arg()...);
122 },
123 m_AdditionalArgs);
124 }
125
126 [[nodiscard]]
127 constexpr StringT describe() const
128 {
129 return std::apply(
130 [&, this](auto&... additionalArgs) {
131 return format::vformat(
132 m_FormatString,
133 format::make_format_args(
134 std::invoke(
135 // std::make_format_args requires lvalue-refs, so let's transform rvalue-refs to const lvalue-refs
136 [](auto&& val) noexcept -> const auto& { return val; },
137 additionalArgs.as_describe_arg())...));
138 },
139 m_AdditionalArgs);
140 }
141
142 [[nodiscard]]
143 constexpr auto operator!() const&
144 requires std::is_copy_constructible_v<Predicate>
145 && std::is_copy_constructible_v<storage_t>
146 {
147 return make_inverted(
148 m_Predicate,
149 m_InvertedFormatString,
150 m_FormatString,
151 m_AdditionalArgs);
152 }
153
154 [[nodiscard]]
155 constexpr auto operator!() &&
156 {
157 return make_inverted(
158 std::move(m_Predicate),
159 std::move(m_InvertedFormatString),
160 std::move(m_FormatString),
161 std::move(m_AdditionalArgs));
162 }
163
164 private:
165 [[no_unique_address]] Predicate m_Predicate;
166 StringViewT m_FormatString;
167 StringViewT m_InvertedFormatString;
168 storage_t m_AdditionalArgs;
169
170 template <typename Fn>
171 [[nodiscard]]
172 static constexpr auto make_inverted(
173 Fn&& fn,
174 StringViewT fmt,
175 StringViewT invertedFmt,
176 storage_t tuple)
177 {
178 using NotFnT = decltype(std::not_fn(std::forward<Fn>(fn)));
180 std::not_fn(std::forward<Fn>(fn)),
181 std::move(fmt),
182 std::move(invertedFmt),
183 std::move(tuple)};
184 }
185 };
186
193 {
194 public:
195 [[nodiscard]]
196 static constexpr bool matches([[maybe_unused]] auto&& target) noexcept
197 {
198 return true;
199 }
200
201 [[nodiscard]]
202 static constexpr std::nullopt_t describe() noexcept
203 {
204 return std::nullopt;
205 }
206 };
207
213 template <typename T>
215 {
216 public:
217 template <typename U>
218 using is_accepting = std::is_same<T, U>;
219
220 [[nodiscard]]
221 static constexpr bool matches([[maybe_unused]] auto&& target) noexcept
222 {
223 return true;
224 }
225
226 [[nodiscard]]
227 static constexpr std::nullopt_t describe() noexcept
228 {
229 return std::nullopt;
230 }
231 };
232}
233
235{
284
289 [[maybe_unused]] inline constexpr WildcardMatcher _{};
290
296 template <typename T>
297 [[maybe_unused]] inline constexpr TypeMatcher<T> type{};
298
304 template <typename T>
305 [[nodiscard]]
306 constexpr auto eq(T&& value)
307 {
308 return PredicateMatcher{
309 std::equal_to{},
310 "== {}",
311 "!= {}",
312 std::make_tuple(std::forward<T>(value))};
313 }
314
320 template <typename T>
321 [[nodiscard]]
322 constexpr auto ne(T&& value)
323 {
324 return PredicateMatcher{
325 std::not_equal_to{},
326 "!= {}",
327 "== {}",
328 std::make_tuple(std::forward<T>(value))};
329 }
330
336 template <typename T>
337 [[nodiscard]]
338 constexpr auto lt(T&& value)
339 {
340 return PredicateMatcher{
341 std::less{},
342 "< {}",
343 ">= {}",
344 std::make_tuple(std::forward<T>(value))};
345 }
346
352 template <typename T>
353 [[nodiscard]]
354 constexpr auto le(T&& value)
355 {
356 return PredicateMatcher{
357 std::less_equal{},
358 "<= {}",
359 "> {}",
360 std::make_tuple(std::forward<T>(value))};
361 }
362
368 template <typename T>
369 [[nodiscard]]
370 constexpr auto gt(T&& value)
371 {
372 return PredicateMatcher{
373 std::greater{},
374 "> {}",
375 "<= {}",
376 std::make_tuple(std::forward<T>(value))};
377 }
378
384 template <typename T>
385 [[nodiscard]]
386 constexpr auto ge(T&& value)
387 {
388 return PredicateMatcher{
389 std::greater_equal{},
390 ">= {}",
391 "< {}",
392 std::make_tuple(std::forward<T>(value))};
393 }
394
403 template <typename UnaryPredicate>
404 [[nodiscard]]
405 constexpr auto predicate(
406 UnaryPredicate&& predicate,
407 StringViewT description = "passes predicate",
408 StringViewT invertedDescription = "fails predicate")
409 {
410 return PredicateMatcher{
411 std::forward<UnaryPredicate>(predicate),
412 std::move(description),
413 std::move(invertedDescription),
414 };
415 }
416
423 template <util::satisfies<std::is_lvalue_reference> T>
424 [[nodiscard]]
425 constexpr auto instance(T&& instance) // NOLINT(cppcoreguidelines-missing-std-forward)
426 {
427 return PredicateMatcher{
428 []<typename Other>(Other const& target, auto const* instancePtr) noexcept
429 requires std::is_convertible_v<std::remove_cvref_t<T> const volatile*, Other const volatile*>
430 {
431 return std::addressof(target) == instancePtr;
432 },
433 "is instance at {}",
434 "is not instance at {}",
435 std::make_tuple(std::addressof(instance))};
436 }
437
441}
442
443#endif
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Generic matcher and the basic building block of most of the built-in matchers.
Definition GeneralMatchers.hpp:75
constexpr bool matches(First &first, Others &... others) const noexcept(std::is_nothrow_invocable_v< const Predicate &, First &, Others &..., matches_reference_t< AdditionalArgs >... >)
Definition GeneralMatchers.hpp:105
constexpr auto operator!() const &
Definition GeneralMatchers.hpp:143
constexpr auto operator!() &&
Definition GeneralMatchers.hpp:155
constexpr StringT describe() const
Definition GeneralMatchers.hpp:127
constexpr PredicateMatcher(Predicate predicate, StringViewT fmt, StringViewT invertedFmt, std::tuple< AdditionalArgs... > additionalArgs={}) noexcept(std::is_nothrow_move_constructible_v< Predicate > &&(... &&std::is_nothrow_move_constructible_v< AdditionalArgs >))
Definition GeneralMatchers.hpp:83
Matcher, which can be used to disambiguate between similar overloads.
Definition GeneralMatchers.hpp:215
std::is_same< T, U > is_accepting
Definition GeneralMatchers.hpp:218
static constexpr std::nullopt_t describe() noexcept
Definition GeneralMatchers.hpp:227
static constexpr bool matches(auto &&target) noexcept
Definition GeneralMatchers.hpp:221
Matcher, which never fails.
Definition GeneralMatchers.hpp:193
static constexpr bool matches(auto &&target) noexcept
Definition GeneralMatchers.hpp:196
static constexpr std::nullopt_t describe() noexcept
Definition GeneralMatchers.hpp:202
constexpr auto lt(T &&value)
Tests, whether the target is less than the expected value.
Definition GeneralMatchers.hpp:338
constexpr auto instance(T &&instance)
Tests, whether the target is the expected instance.
Definition GeneralMatchers.hpp:425
constexpr auto le(T &&value)
Tests, whether the target is less than or equal to the expected value.
Definition GeneralMatchers.hpp:354
constexpr TypeMatcher< T > type
Matcher, which can be used as a last resort to disambiguate similar overloads.
Definition GeneralMatchers.hpp:297
constexpr WildcardMatcher _
The wildcard matcher, always matching.
Definition GeneralMatchers.hpp:289
constexpr auto eq(T &&value)
Tests, whether the target compares equal to the expected value.
Definition GeneralMatchers.hpp:306
constexpr auto gt(T &&value)
Tests, whether the target is greater than the expected value.
Definition GeneralMatchers.hpp:370
constexpr auto predicate(UnaryPredicate &&predicate, StringViewT description="passes predicate", StringViewT invertedDescription="fails predicate")
Tests, whether the target fulfills the given predicate.
Definition GeneralMatchers.hpp:405
constexpr auto ge(T &&value)
Tests, whether the target is greater than or equal to the expected value.
Definition GeneralMatchers.hpp:386
constexpr auto ne(T &&value)
Tests, whether the target compares not equal to the expected value.
Definition GeneralMatchers.hpp:322
Definition FloatingPointMatchers.hpp:25
Definition Call.hpp:24
std::basic_string_view< CharT, CharTraitsT > StringViewT
Definition Fwd.hpp:392
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:391