Sequoia
Loading...
Searching...
No Matches
MoveOnlyAllocationCheckersDetails.hpp
Go to the documentation of this file.
1
2// Copyright Oliver J. Rosten 2020. //
3// Distributed under the GNU GENERAL PUBLIC LICENSE, Version 3.0. //
4// (See accompanying file LICENSE.md or copy at //
5// https://www.gnu.org/licenses/gpl-3.0.en.html) //
7
8#pragma once
9
16
17#include <optional>
18
20{
21 template<moveonly T>
23 {
24 using allocation_actions<T>::allocation_actions;
25 };
26
27 template<test_mode Mode, class Actions, moveonly T, class U, alloc_getter<T>... Getters>
28 requires checkable_against_for_semantics<Mode, T, U>
29 bool check_swap(test_logger<Mode>& logger, const Actions& actions, T&& x, T&& y, const U& xEquivalent, const U& yEquivalent, const dual_allocation_checker<T, Getters>&... checkers)
30 {
31 return do_check_swap(logger, actions, std::move(x), std::move(y), xEquivalent, yEquivalent, dual_allocation_checker{checkers.info(), x, y}...);
32 }
33
34 template<test_mode Mode, container_tag tag, moveonly T, class U, alloc_getter<T>... Getters>
35 requires checkable_against_for_semantics<Mode, T, U>
36 std::optional<T> check_para_constructor_allocations(test_logger<Mode>& logger,
37 container_tag_constant<tag>,
38 T&& z,
39 const U& zEquivalent,
40 const allocation_info<T, Getters>&... info)
41 {
42 const auto tagStr{to_string(container_tag_constant<tag>::value)};
43
44 using check_type = std::conditional_t<std::is_same_v<std::remove_cvref_t<T>, U>, simple_equality_check_t, with_best_available_check_t<minimal_reporting_permitted::yes>>;
45
46 if(!check(check_type{},
47 std::format("Prerequisite - for checking move-only semantics, {}and {} Equivalent are assumed to be equal", tagStr, tagStr),
48 logger,
49 z,
50 zEquivalent))
51 {
52 return{};
53 }
54
55 T v{std::move(z), info.make_allocator()...};
56
57 using ctag = container_tag_constant<tag>;
58 check_para_move_allocation(logger, ctag{}, v, std::tuple_cat(make_allocation_checkers(info)...));
59 if(check(with_best_available, "Inonsistent para-move constructor", logger, v, zEquivalent))
60 {
61 std::optional<T> w{std::move(v)};
62 if(check(with_best_available, "Inconsistent move construction", logger, *w, zEquivalent))
63 {
64 return w;
65 }
66 }
67
68 return std::nullopt;
69 }
70
71 template<test_mode Mode, moveonly T, class U, alloc_getter<T>... Getters>
72 requires checkable_against_for_semantics<Mode, T, U>
73 std::pair<std::optional<T>, std::optional<T>>
74 check_para_constructor_allocations(test_logger<Mode>& logger,
75 T&& x,
76 T&& y,
77 const U& xEquivalent,
78 const U& yEquivalent,
79 const allocation_info<T, Getters>&... info)
80 {
81 return {check_para_constructor_allocations(logger, container_tag_constant<container_tag::x>{}, std::forward<T>(x), xEquivalent, info...),
82 check_para_constructor_allocations(logger, container_tag_constant<container_tag::y>{}, std::forward<T>(y), yEquivalent, info...)};
83 }
84
85 template<test_mode Mode, class Actions, moveonly T, class U, std::invocable<T&> Mutator, alloc_getter<T>... Getters>
86 requires checkable_against_for_semantics<Mode, T, U> && (sizeof...(Getters) > 0)
87 void check_semantics(std::string description,
88 test_logger<Mode>& logger,
89 const Actions& actions,
90 T&& x,
91 T&& y,
92 const U& xEquivalent,
93 const U& yEquivalent,
94 optional_ref<const U> movedFromPostConstruction,
95 optional_ref<const U> movedFromPostAssignment,
96 Mutator m,
97 const allocation_info<T, Getters>&... info)
98 {
99 const auto message{!description.empty() ? add_type_info<T>(std::move(description)).append("\n") : ""};
100 sentinel<Mode> sentry{logger, message};
101
102 if(auto[optx,opty]{check_para_constructor_allocations(logger, std::forward<T>(x), std::forward<T>(y), xEquivalent, yEquivalent, info...)}; (optx != std::nullopt) && (opty != std::nullopt))
103 {
104 check_semantics(logger,
105 actions,
106 std::move(*optx),
107 std::move(*opty),
108 xEquivalent,
109 yEquivalent,
110 movedFromPostConstruction,
111 movedFromPostAssignment,
112 std::move(m),
113 std::tuple_cat(make_dual_allocation_checkers(info, x, y)...));
114 }
115 }
116
117 template
118 <
119 test_mode Mode,
120 class Actions,
121 moveonly T,
122 invocable_r<T> xMaker,
123 invocable_r<T> yMaker,
124 std::invocable<T&> Mutator,
125 alloc_getter<T>... Getters
126 >
127 requires (sizeof...(Getters) > 0)
128 std::pair<T,T> check_semantics(std::string description,
129 test_logger<Mode>& logger,
130 const Actions& actions,
131 xMaker xFn,
132 yMaker yFn,
133 optional_ref<const T> movedFromPostConstruction,
134 optional_ref<const T> movedFromPostAssignment,
135 Mutator m,
136 const allocation_info<T, Getters>&... info)
137 {
138 sentinel<Mode> sentry{logger, add_type_info<T>(std::move(description)).append("\n")};
139
140 auto x{xFn()};
141 auto y{yFn()};
142
143 impl::check_initialization_allocations(logger, x, y, info...);
144 check_semantics("", logger, actions, xFn(), yFn(), x, y, movedFromPostConstruction, movedFromPostAssignment, std::move(m), info...);
145
146 return {std::move(x), std::move(y)};
147 }
148
150 template<test_mode Mode, class Actions, moveonly T, class U, std::invocable<T&> Mutator, alloc_getter<T>... Getters>
151 requires checkable_against_for_semantics<Mode, T, U> && (sizeof...(Getters) > 0)
152 void check_semantics(test_logger<Mode>& logger,
153 const Actions& actions,
154 T&& x,
155 T&& y,
156 const U& xEquivalent,
157 const U& yEquivalent,
158 optional_ref<const U> movedFromPostConstruction,
159 optional_ref<const U> movedFromPostAssignment,
160 Mutator m,
161 std::tuple<dual_allocation_checker<T, Getters>...> checkers)
162 {
163 auto fn{
164 [&,m{std::move(m)}](auto&&... checkers){
165 return check_semantics(logger,
166 actions,
167 std::forward<T>(x),
168 std::forward<T>(y),
169 xEquivalent,
170 yEquivalent,
171 movedFromPostConstruction,
172 movedFromPostAssignment,
173 std::move(m),
174 std::forward<decltype(checkers)>(checkers)...);
175 }
176 };
177
178 std::apply(fn, std::move(checkers));
179 }
180}
Implementation details for allocation checks.
bool check(CheckType flavour, std::string description, test_logger< Mode > &logger, Iter first, Sentinel last, PredictionIter predictionFirst, PredictionSentinel predictionLast, tutor< Advisor > advisor={})
The workhorse for comparing the contents of ranges.
Definition: FreeCheckers.hpp:377
Implementation details for checking move-only semantics.
Wraps allocation_info, together with two prior allocation counts.
Definition: AllocationCheckersDetails.hpp:60
Definition: TestLogger.hpp:183
Condition for applying a container check.
Definition: AllocationCheckersDetails.cpp:15
actions common to both move-only and regular types.
Definition: AllocationCheckersDetails.hpp:603
Definition: MoveOnlyAllocationCheckersDetails.hpp:23