mimic++ v4
Loading...
Searching...
No Matches
Matcher.hpp
Go to the documentation of this file.
1// // Copyright Dominic (DNKpp) Koepke 2024 - 2024.
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_MATCHER_HPP
7#define MIMICPP_MATCHER_HPP
8
9#pragma once
10
11#include "mimic++/Fwd.hpp"
12#include "mimic++/Printer.hpp"
13#include "mimic++/String.hpp"
15#include "mimic++/Utility.hpp"
16
17#include <algorithm>
18#include <concepts>
19#include <functional>
20#include <optional>
21#include <ranges>
22#include <tuple>
23#include <type_traits>
24
26{
27 template <typename Matcher>
29}
30
31namespace mimicpp::detail::matches_hook
32{
33 template <typename Matcher, typename T>
34 [[nodiscard]]
35 constexpr bool matches_impl(
36 const Matcher& matcher,
37 T& target,
38 [[maybe_unused]] const priority_tag<1>
39 )
40 requires requires
41 {
42 {
43 custom::matcher_traits<Matcher>{}.matches(matcher, target)
44 } -> std::convertible_to<bool>;
45 }
46 {
47 return custom::matcher_traits<Matcher>{}.matches(matcher, target);
48 }
49
50 template <typename Matcher, typename T>
51 [[nodiscard]]
52 constexpr bool matches_impl(
53 const Matcher& matcher,
54 T& target,
55 [[maybe_unused]] const priority_tag<0>
56 )
57 requires requires { { matcher.matches(target) } -> std::convertible_to<bool>; }
58 {
59 return matcher.matches(target);
60 }
61
62 constexpr priority_tag<1> maxTag;
63
64 template <typename Matcher, typename T>
65 [[nodiscard]]
66 constexpr bool matches(const Matcher& matcher, T& target)
67 requires requires { { matches_impl(matcher, target, maxTag) } -> std::convertible_to<bool>; }
68 {
69 return matches_impl(matcher, target, maxTag);
70 }
71}
72
73namespace mimicpp::detail::describe_hook
74{
75 template <typename Matcher>
76 [[nodiscard]]
77 constexpr decltype(auto) describe_impl(
78 const Matcher& matcher,
79 [[maybe_unused]] const priority_tag<1>
80 )
81 requires requires
82 {
83 {
84 custom::matcher_traits<Matcher>{}.describe(matcher)
85 } -> std::convertible_to<StringViewT>;
86 }
87 {
88 return custom::matcher_traits<Matcher>{}.describe(matcher);
89 }
90
91 template <typename Matcher>
92 [[nodiscard]]
93 constexpr decltype(auto) describe_impl(
94 const Matcher& matcher,
95 [[maybe_unused]] const priority_tag<0>
96 )
97 requires requires { { matcher.describe() } -> std::convertible_to<StringViewT>; }
98 {
99 return matcher.describe();
100 }
101
102 constexpr priority_tag<1> maxTag;
103
104 template <typename Matcher>
105 [[nodiscard]]
106 constexpr decltype(auto) describe(const Matcher& matcher)
107 requires requires { { describe_impl(matcher, maxTag) } -> std::convertible_to<StringViewT>; }
108 {
109 return describe_impl(matcher, maxTag);
110 }
111}
112
113namespace mimicpp
114{
115 template <typename T, typename Target>
116 concept matcher_for = std::same_as<T, std::remove_cvref_t<T>>
117 && std::is_move_constructible_v<T>
118 && std::destructible<T>
119 && requires(const T& matcher, Target& target)
120 {
121 { detail::matches_hook::matches(matcher, target) } -> std::convertible_to<bool>;
122 { detail::describe_hook::describe(matcher) } -> std::convertible_to<StringViewT>;
123 };
124
125 namespace detail
126 {
127 template <typename Arg, typename MatchesProjection = std::identity, typename DescribeProjection = PrintFn>
128 struct arg_storage
129 {
130 using matches_reference = std::invoke_result_t<MatchesProjection, const Arg&>;
131 using describe_reference = std::invoke_result_t<DescribeProjection, const Arg&>;
132
133 Arg arg;
134
135 decltype(auto) as_matches_arg() const noexcept(std::is_nothrow_invocable_v<MatchesProjection, const Arg&>)
136 {
137 return std::invoke(MatchesProjection{}, arg);
138 }
139
140 decltype(auto) as_describe_arg() const noexcept(std::is_nothrow_invocable_v<DescribeProjection, const Arg&>)
141 {
142 return std::invoke(DescribeProjection{}, arg);
143 }
144 };
145
146 template <typename T>
147 struct to_arg_storage
148 {
149 using type = arg_storage<T>;
150 };
151
152 template <typename Arg, typename MatchesProjection, typename DescribeProjection>
153 struct to_arg_storage<arg_storage<Arg, MatchesProjection, DescribeProjection>>
154 {
155 using type = arg_storage<Arg, MatchesProjection, DescribeProjection>;
156 };
157
158 template <typename T>
159 using to_arg_storage_t = typename to_arg_storage<T>::type;
160 }
161
169 template <typename Predicate, typename... AdditionalArgs>
170 requires std::is_move_constructible_v<Predicate>
171 && (... && std::is_move_constructible_v<AdditionalArgs>)
173 {
174 private:
175 using storage_t = std::tuple<detail::to_arg_storage_t<AdditionalArgs>...>;
176 template <typename T>
177 using matches_reference_t = typename detail::to_arg_storage_t<T>::matches_reference;
178
179 public:
180 [[nodiscard]]
181 explicit constexpr PredicateMatcher(
182 Predicate predicate,
183 StringT fmt,
184 StringT invertedFmt,
185 std::tuple<AdditionalArgs...> additionalArgs = {}
186 ) noexcept(std::is_nothrow_move_constructible_v<Predicate>
187 && (... && std::is_nothrow_move_constructible_v<AdditionalArgs>))
188 : m_Predicate{std::move(predicate)},
189 m_FormatString{std::move(fmt)},
190 m_InvertedFormatString{std::move(invertedFmt)},
191 m_AdditionalArgs{std::move(additionalArgs)}
192 {
193 }
194
195 template <typename T>
196 requires std::predicate<
197 const Predicate&,
198 T&,
199 matches_reference_t<AdditionalArgs>...>
200 [[nodiscard]]
201 constexpr bool matches(
202 T& target
203 ) const noexcept(std::is_nothrow_invocable_v<const Predicate&, T&, matches_reference_t<AdditionalArgs>...>)
204 {
205 return std::apply(
206 [&, this](auto&... additionalArgs)
207 {
208 return std::invoke(
209 m_Predicate,
210 target,
211 additionalArgs.as_matches_arg()...);
212 },
213 m_AdditionalArgs);
214 }
215
216 [[nodiscard]]
217 constexpr StringT describe() const
218 {
219 return std::apply(
220 [&, this](auto&... additionalArgs)
221 {
222 return format::vformat(
223 m_FormatString,
224 format::make_format_args(
225 std::invoke(
226 // std::make_format_args requires lvalue-refs, so let's transform rvalue-refs to const lvalue-refs
227 [](auto&& val) noexcept -> const auto& { return val; },
228 additionalArgs.as_describe_arg())
229 ...));
230 },
231 m_AdditionalArgs);
232 }
233
234 [[nodiscard]]
235 constexpr auto operator !() const &
236 requires std::is_copy_constructible_v<Predicate>
237 && std::is_copy_constructible_v<storage_t>
238 {
239 return make_inverted(
240 m_Predicate,
241 m_InvertedFormatString,
242 m_FormatString,
243 m_AdditionalArgs);
244 }
245
246 [[nodiscard]]
247 constexpr auto operator !() &&
248 {
249 return make_inverted(
250 std::move(m_Predicate),
251 std::move(m_InvertedFormatString),
252 std::move(m_FormatString),
253 std::move(m_AdditionalArgs));
254 }
255
256 private:
257 [[no_unique_address]] Predicate m_Predicate;
258 StringT m_FormatString;
259 StringT m_InvertedFormatString;
260 storage_t m_AdditionalArgs;
261
262 template <typename Fn>
263 [[nodiscard]]
264 static constexpr auto make_inverted(
265 Fn&& fn,
266 StringT fmt,
267 StringT invertedFmt,
268 storage_t tuple
269 )
270 {
271 using NotFnT = decltype(std::not_fn(std::forward<Fn>(fn)));
273 std::not_fn(std::forward<Fn>(fn)),
274 std::move(fmt),
275 std::move(invertedFmt),
276 std::move(tuple)
277 };
278 }
279 };
280
288 {
289 public:
290 static constexpr bool matches([[maybe_unused]] auto&& target) noexcept
291 {
292 return true;
293 }
294
295 static constexpr StringViewT describe() noexcept
296 {
297 return "has no constraints";
298 }
299 };
300}
301
303{
341 [[maybe_unused]] inline constexpr WildcardMatcher _{};
342
348 template <typename T>
349 [[nodiscard]]
350 constexpr auto eq(T&& value)
351 {
352 return PredicateMatcher{
353 std::equal_to{},
354 "== {}",
355 "!= {}",
356 std::tuple{std::forward<T>(value)}
357 };
358 }
359
365 template <typename T>
366 [[nodiscard]]
367 constexpr auto ne(T&& value)
368 {
369 return PredicateMatcher{
370 std::not_equal_to{},
371 "!= {}",
372 "== {}",
373 std::tuple{std::forward<T>(value)}
374 };
375 }
376
382 template <typename T>
383 [[nodiscard]]
384 constexpr auto lt(T&& value)
385 {
386 return PredicateMatcher{
387 std::less{},
388 "< {}",
389 ">= {}",
390 std::tuple{std::forward<T>(value)}
391 };
392 }
393
399 template <typename T>
400 [[nodiscard]]
401 constexpr auto le(T&& value)
402 {
403 return PredicateMatcher{
404 std::less_equal{},
405 "<= {}",
406 "> {}",
407 std::tuple{std::forward<T>(value)}
408 };
409 }
410
416 template <typename T>
417 [[nodiscard]]
418 constexpr auto gt(T&& value)
419 {
420 return PredicateMatcher{
421 std::greater{},
422 "> {}",
423 "<= {}",
424 std::tuple{std::forward<T>(value)}
425 };
426 }
427
433 template <typename T>
434 [[nodiscard]]
435 constexpr auto ge(T&& value)
436 {
437 return PredicateMatcher{
438 std::greater_equal{},
439 ">= {}",
440 "< {}",
441 std::tuple{std::forward<T>(value)}
442 };
443 }
444
453 template <typename UnaryPredicate>
454 [[nodiscard]]
455 constexpr auto predicate(
456 UnaryPredicate&& predicate,
457 StringT description = "passes predicate",
458 StringT invertedDescription = "fails predicate"
459 )
460 {
461 return PredicateMatcher{
462 std::forward<UnaryPredicate>(predicate),
463 std::move(description),
464 std::move(invertedDescription),
465 };
466 }
467
474 template <satisfies<std::is_lvalue_reference> T>
475 [[nodiscard]]
476 constexpr auto instance(T&& instance) // NOLINT(cppcoreguidelines-missing-std-forward)
477 {
478 return PredicateMatcher{
479 [](const std::remove_cvref_t<T>& target, const auto* instancePtr) noexcept
480 {
481 return std::addressof(target) == instancePtr;
482 },
483 "is instance at {}",
484 "is not instance at {}",
485 std::tuple{std::addressof(instance)}
486 };
487 }
488
492}
493
494namespace mimicpp
495{
501 {
502 } constexpr case_insensitive{};
503}
504
505namespace mimicpp::matches::detail
506{
507 template <string String>
508 [[nodiscard]]
509 constexpr auto make_view(String&& str)
510 {
511 using traits_t = string_traits<std::remove_cvref_t<String>>;
512 return traits_t::view(std::forward<String>(str));
513 }
514
515 template <case_foldable_string String>
516 [[nodiscard]]
517 constexpr auto make_case_folded_string(String&& str)
518 {
519 return std::invoke(
520 string_case_fold_converter<string_char_t<String>>{},
521 detail::make_view(std::forward<String>(str)));
522 }
523
524 template <string Target, string Pattern>
525 constexpr void check_string_compatibility() noexcept
526 {
527 static_assert(
528 std::same_as<
531 "Pattern and target string must have the same character-type.");
532 }
533}
534
536{
592 template <string Pattern>
593 [[nodiscard]]
594 constexpr auto eq(Pattern&& pattern)
595 {
596 return PredicateMatcher{
597 []<string T, typename Stored>(T&& target, Stored&& stored)
598 {
599 detail::check_string_compatibility<T, Pattern>();
600
601 return std::ranges::equal(
602 detail::make_view(std::forward<T>(target)),
603 detail::make_view(std::forward<Stored>(stored)));
604 },
605 "is equal to {}",
606 "is not equal to {}",
607 std::tuple{std::forward<Pattern>(pattern)}
608 };
609 }
610
616 template <case_foldable_string Pattern>
617 [[nodiscard]]
618 constexpr auto eq(Pattern&& pattern, [[maybe_unused]] const case_insensitive_t)
619 {
620 return PredicateMatcher{
621 []<case_foldable_string T, typename Stored>(T&& target, Stored&& stored)
622 {
623 detail::check_string_compatibility<T, Pattern>();
624
625 return std::ranges::equal(
626 detail::make_case_folded_string(std::forward<T>(target)),
627 detail::make_case_folded_string(std::forward<Stored>(stored)));
628 },
629 "is case-insensitively equal to {}",
630 "is case-insensitively not equal to {}",
631 std::tuple{std::forward<Pattern>(pattern)}
632 };
633 }
634
640 template <string Pattern>
641 [[nodiscard]]
642 constexpr auto starts_with(Pattern&& pattern)
643 {
644 return PredicateMatcher{
645 []<string T, typename Stored>(T&& target, Stored&& stored)
646 {
647 detail::check_string_compatibility<T, Pattern>();
648
649 auto patternView = detail::make_view(std::forward<Stored>(stored));
650 const auto [ignore, patternIter] = std::ranges::mismatch(
651 detail::make_view(std::forward<T>(target)),
652 patternView);
653
654 return patternIter == std::ranges::end(patternView);
655 },
656 "starts with {}",
657 "starts not with {}",
658 std::tuple{std::forward<Pattern>(pattern)}
659 };
660 }
661
667 template <string Pattern>
668 [[nodiscard]]
669 constexpr auto starts_with(Pattern&& pattern, [[maybe_unused]] const case_insensitive_t)
670 {
671 return PredicateMatcher{
672 []<string T, typename Stored>(T&& target, Stored&& stored)
673 {
674 detail::check_string_compatibility<T, Pattern>();
675
676 auto caseFoldedPattern = detail::make_case_folded_string(std::forward<Stored>(stored));
677 const auto [ignore, patternIter] = std::ranges::mismatch(
678 detail::make_case_folded_string(std::forward<T>(target)),
679 caseFoldedPattern);
680
681 return patternIter == std::ranges::end(caseFoldedPattern);
682 },
683 "case-insensitively starts with {}",
684 "case-insensitively starts not with {}",
685 std::tuple{std::forward<Pattern>(pattern)}
686 };
687 }
688
694 template <string Pattern>
695 [[nodiscard]]
696 constexpr auto ends_with(Pattern&& pattern)
697 {
698 return PredicateMatcher{
699 []<string T, typename Stored>(T&& target, Stored&& stored)
700 {
701 detail::check_string_compatibility<T, Pattern>();
702
703 auto patternView = detail::make_view(std::forward<Stored>(stored))
704 | std::views::reverse;
705 const auto [ignore, patternIter] = std::ranges::mismatch(
706 detail::make_view(std::forward<T>(target)) | std::views::reverse,
707 patternView);
708
709 return patternIter == std::ranges::end(patternView);
710 },
711 "ends with {}",
712 "ends not with {}",
713 std::tuple{std::forward<Pattern>(pattern)}
714 };
715 }
716
722 template <string Pattern>
723 [[nodiscard]]
724 constexpr auto ends_with(Pattern&& pattern, [[maybe_unused]] const case_insensitive_t)
725 {
726 return PredicateMatcher{
727 []<string T, typename Stored>(T&& target, Stored&& stored)
728 {
729 detail::check_string_compatibility<T, Pattern>();
730
731 auto caseFoldedPattern = detail::make_case_folded_string(std::forward<Stored>(stored))
732 | std::views::reverse;
733 const auto [ignore, patternIter] = std::ranges::mismatch(
734 detail::make_case_folded_string(std::forward<T>(target)) | std::views::reverse,
735 caseFoldedPattern);
736
737 return patternIter == std::ranges::end(caseFoldedPattern);
738 },
739 "case-insensitively ends with {}",
740 "case-insensitively ends not with {}",
741 std::tuple{std::forward<Pattern>(pattern)}
742 };
743 }
744
750 template <string Pattern>
751 [[nodiscard]]
752 constexpr auto contains(Pattern&& pattern)
753 {
754 return PredicateMatcher{
755 []<string T, typename Stored>(T&& target, Stored&& stored)
756 {
757 detail::check_string_compatibility<T, Pattern>();
758
759 auto patternView = detail::make_view(std::forward<Stored>(stored));
760 return std::ranges::empty(patternView)
761 || !std::ranges::empty(
762 std::ranges::search(
763 detail::make_view(std::forward<T>(target)),
764 std::move(patternView)));
765 },
766 "contains {}",
767 "contains not {}",
768 std::tuple{std::forward<Pattern>(pattern)}
769 };
770 }
771
777 template <string Pattern>
778 [[nodiscard]]
779 constexpr auto contains(Pattern&& pattern, [[maybe_unused]] const case_insensitive_t)
780 {
781 return PredicateMatcher{
782 []<string T, typename Stored>(T&& target, Stored&& stored)
783 {
784 detail::check_string_compatibility<T, Pattern>();
785
786 auto patternView = detail::make_case_folded_string(std::forward<Stored>(stored));
787 auto targetView = detail::make_case_folded_string(std::forward<T>(target));
788 return std::ranges::empty(patternView)
789 || !std::ranges::empty(std::ranges::search(targetView, patternView));
790 },
791 "case-insensitively contains {}",
792 "case-insensitively contains not {}",
793 std::tuple{std::forward<Pattern>(pattern)}
794 };
795 }
796
800}
801
803{
820 template <std::ranges::forward_range Range, typename Comparator = std::equal_to<>>
821 [[nodiscard]]
822 constexpr auto eq(Range&& expected, Comparator comparator = Comparator{})
823 {
824 return PredicateMatcher{
825 [comp = std::move(comparator)]
826 <typename Target>(Target&& target, auto& range) // NOLINT(cppcoreguidelines-missing-std-forward)
827 requires std::predicate<
828 const Comparator&,
829 std::ranges::range_reference_t<Target>,
830 std::ranges::range_reference_t<Range>>
831 {
832 return std::ranges::equal(
833 target,
834 range,
835 std::ref(comp));
836 },
837 "elements are {}",
838 "elements are not {}",
839 std::tuple{std::views::all(std::forward<Range>(expected))}
840 };
841 }
842
850 template <std::ranges::forward_range Range, typename Comparator = std::equal_to<>>
851 [[nodiscard]]
852 constexpr auto unordered_eq(Range&& expected, Comparator comparator = Comparator{})
853 {
854 return PredicateMatcher{
855 [comp = std::move(comparator)]<typename Target
856 >(Target&& target, auto& range) // NOLINT(cppcoreguidelines-missing-std-forward)
857 requires std::predicate<
858 const Comparator&,
859 std::ranges::range_reference_t<Target>,
860 std::ranges::range_reference_t<Range>>
861 {
862 return std::ranges::is_permutation(
863 target,
864 range,
865 std::ref(comp));
866 },
867 "is a permutation of {}",
868 "is not a permutation of {}",
869 std::tuple{std::views::all(std::forward<Range>(expected))}
870 };
871 }
872
878 template <typename Relation = std::ranges::less>
879 [[nodiscard]]
880 constexpr auto is_sorted(Relation relation = Relation{})
881 {
882 return PredicateMatcher{
883 [rel = std::move(relation)]<typename Target>(Target&& target) // NOLINT(cppcoreguidelines-missing-std-forward)
884 requires std::equivalence_relation<
885 const Relation&,
886 std::ranges::range_reference_t<Target>,
887 std::ranges::range_reference_t<Target>>
888 {
889 return std::ranges::is_sorted(
890 target,
891 std::ref(rel));
892 },
893 "is a sorted range",
894 "is an unsorted range"
895 };
896 }
897
901 [[nodiscard]]
902 constexpr auto is_empty()
903 {
904 return PredicateMatcher{
905 [](std::ranges::range auto&& target)
906 {
907 return std::ranges::empty(target);
908 },
909 "is an empty range",
910 "is not an empty range"
911 };
912 }
913
918 [[nodiscard]]
919 constexpr auto has_size(const std::integral auto expected)
920 {
921 return PredicateMatcher{
922 [](std::ranges::range auto&& target, const std::integral auto size)
923 {
924 return std::cmp_equal(
925 size,
926 std::ranges::size(target));
927 },
928 "has size of {}",
929 "has different size than {}",
930 std::tuple{expected}
931 };
932 }
933
938 template <typename Matcher>
939 [[nodiscard]]
940 constexpr auto each_element(Matcher&& matcher)
941 {
942 using MatcherT = std::remove_cvref_t<Matcher>;
943 return PredicateMatcher{
944 [](std::ranges::range auto&& target, const MatcherT& m)
945 {
946 return std::ranges::all_of(
947 target,
948 [&](const auto& element) { return m.matches(element); });
949 },
950 "each el in range: el {}",
951 "not each el in range: el {}",
952 std::tuple{
953 mimicpp::detail::arg_storage<
954 MatcherT,
955 std::identity,
956 decltype([](const auto& m) { return mimicpp::detail::describe_hook::describe(m); })>{
957 std::forward<MatcherT>(matcher)
958 }
959 }
960 };
961 }
962
967 template <typename Matcher>
968 [[nodiscard]]
969 constexpr auto any_element(Matcher&& matcher)
970 {
971 using MatcherT = std::remove_cvref_t<Matcher>;
972 return PredicateMatcher{
973 [](std::ranges::range auto&& target, const MatcherT& m)
974 {
975 return std::ranges::any_of(
976 target,
977 [&](const auto& element) { return m.matches(element); });
978 },
979 "any el in range: el {}",
980 "none el in range: el {}",
981 std::tuple{
982 mimicpp::detail::arg_storage<
983 MatcherT,
984 std::identity,
985 decltype([](const auto& m) { return mimicpp::detail::describe_hook::describe(m); })>{
986 std::forward<MatcherT>(matcher)
987 }
988 }
989 };
990 }
991
995}
996
997#endif
Generic matcher and the basic building block of most of the built-in matchers.
Definition Matcher.hpp:173
constexpr PredicateMatcher(Predicate predicate, StringT fmt, StringT invertedFmt, std::tuple< AdditionalArgs... > additionalArgs={}) noexcept(std::is_nothrow_move_constructible_v< Predicate > &&(... &&std::is_nothrow_move_constructible_v< AdditionalArgs >))
Definition Matcher.hpp:181
constexpr StringT describe() const
Definition Matcher.hpp:217
constexpr bool matches(T &target) const noexcept(std::is_nothrow_invocable_v< const Predicate &, T &, matches_reference_t< AdditionalArgs >... >)
Definition Matcher.hpp:201
Matcher, which never fails.
Definition Matcher.hpp:288
static constexpr bool matches(auto &&target) noexcept
Definition Matcher.hpp:290
static constexpr StringViewT describe() noexcept
Definition Matcher.hpp:295
Determines, whether the given type supports string normalization.
Definition String.hpp:377
Definition Matcher.hpp:116
constexpr auto eq(Range &&expected, Comparator comparator=Comparator{})
Tests, whether the target range compares equal to the expected range, by comparing them element-wise.
Definition Matcher.hpp:822
constexpr auto each_element(Matcher &&matcher)
Tests, whether each element of the target range matches the specified matcher.
Definition Matcher.hpp:940
constexpr auto unordered_eq(Range &&expected, Comparator comparator=Comparator{})
Tests, whether the target range is a permutation of the expected range, by comparing them element-wis...
Definition Matcher.hpp:852
constexpr auto any_element(Matcher &&matcher)
Tests, whether any element of the target range matches the specified matcher.
Definition Matcher.hpp:969
constexpr auto has_size(const std::integral auto expected)
Tests, whether the target range has the expected size.
Definition Matcher.hpp:919
constexpr auto is_sorted(Relation relation=Relation{})
Tests, whether the target range is sorted, by applying the relation on each adjacent elements.
Definition Matcher.hpp:880
constexpr auto is_empty()
Tests, whether the target range is empty.
Definition Matcher.hpp:902
constexpr auto lt(T &&value)
Tests, whether the target is less than the expected value.
Definition Matcher.hpp:384
constexpr auto instance(T &&instance)
Tests, whether the target is the expected instance.
Definition Matcher.hpp:476
constexpr auto le(T &&value)
Tests, whether the target is less than or equal to the expected value.
Definition Matcher.hpp:401
constexpr auto predicate(UnaryPredicate &&predicate, StringT description="passes predicate", StringT invertedDescription="fails predicate")
Tests, whether the target fulfills the given predicate.
Definition Matcher.hpp:455
constexpr WildcardMatcher _
The wildcard matcher, always matching.
Definition Matcher.hpp:341
constexpr auto eq(T &&value)
Tests, whether the target compares equal to the expected value.
Definition Matcher.hpp:350
constexpr auto gt(T &&value)
Tests, whether the target is greater than the expected value.
Definition Matcher.hpp:418
constexpr auto ge(T &&value)
Tests, whether the target is greater than or equal to the expected value.
Definition Matcher.hpp:435
constexpr auto ne(T &&value)
Tests, whether the target compares not equal to the expected value.
Definition Matcher.hpp:367
struct mimicpp::case_insensitive_t case_insensitive
constexpr auto eq(Pattern &&pattern)
Tests, whether the target string compares equal to the expected string.
Definition Matcher.hpp:594
constexpr auto ends_with(Pattern &&pattern)
Tests, whether the target string ends with the pattern string.
Definition Matcher.hpp:696
constexpr auto contains(Pattern &&pattern)
Tests, whether the pattern string is part of the target string.
Definition Matcher.hpp:752
constexpr auto starts_with(Pattern &&pattern)
Tests, whether the target string starts with the pattern string.
Definition Matcher.hpp:642
constexpr auto arg(Matcher &&matcher, Projection projection={}) noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Matcher >, Matcher > &&std::is_nothrow_move_constructible_v< Projection >)
Checks, whether the selected argument matches the given matcher.
Definition ExpectationPolicies.hpp:405
typename string_traits< std::remove_cvref_t< T > >::char_t string_char_t
Computes the character type for the given string.
Definition String.hpp:260
Definition Matcher.hpp:26
Definition Matcher.hpp:803
Definition Matcher.hpp:536
Definition Matcher.hpp:303
Definition BoostTest.hpp:20
std::basic_string_view< CharT, CharTraitsT > StringViewT
Definition Fwd.hpp:208
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:207
Tag type, used in string matchers.
Definition Matcher.hpp:501
Definition Matcher.hpp:28
Definition Utility.hpp:32