mimic++ v5
Loading...
Searching...
No Matches
ObjectWatcher.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_OBJECT_WATCHER_HPP
7#define MIMICPP_OBJECT_WATCHER_HPP
8
9#pragma once
10
11#include "mimic++/Mock.hpp"
12
13#include <stdexcept>
14#include <utility>
15
16namespace mimicpp
17{
57 {
58 public:
64 ~LifetimeWatcher() noexcept(false)
65 {
66 if (const auto destruction = std::exchange(
67 m_DestructionMock,
68 nullptr))
69 {
70 (*destruction)();
71 }
72 }
73
77 [[nodiscard]]
78 LifetimeWatcher() = default;
79
90 [[nodiscard]]
91 LifetimeWatcher([[maybe_unused]] const LifetimeWatcher& other)
93 {
94 }
95
111 LifetimeWatcher& operator=([[maybe_unused]] const LifetimeWatcher& other)
112 {
113 // let's make this a two-step.
114 // First destroy the previous instance, which may already report a violation.
115 // If we would already have the new instance created, this would lead also to
116 // a violation report, which actually might break everything.
117 {
118 LifetimeWatcher temp{std::move(*this)};
119 }
120
121 *this = LifetimeWatcher{};
122
123 return *this;
124 }
125
131 [[nodiscard]]
133
140
149 [[nodiscard]]
151 {
152 if (std::exchange(m_HasDestructExpectation, true))
153 {
154 throw std::logic_error{
155 "LifetimeWatcher: A destruct expectation can not be created more than once for a single instance."};
156 }
157
158 return m_DestructionMock->expect_call()
159 and expect::once(); // prevent further times specifications
160 }
161
162 private:
163 bool m_HasDestructExpectation{};
164 std::unique_ptr<Mock<void()>> m_DestructionMock{
165 std::make_unique<Mock<void()>>()};
166 };
167
199 {
200 public:
205
209 [[nodiscard]]
210 RelocationWatcher() = default;
211
219 [[nodiscard]]
220 RelocationWatcher([[maybe_unused]] const RelocationWatcher& other)
222 {
223 }
224
232 RelocationWatcher& operator=([[maybe_unused]] const RelocationWatcher& other)
233 {
234 // explicitly circumvent default construct and assign, because that would
235 // involve the move-assignment.
236 m_RelocationMock = Mock<void()>{};
237
238 return *this;
239 }
240
246 [[nodiscard]]
247 RelocationWatcher(RelocationWatcher&& other) noexcept(false)
248 {
249 *this = std::move(other);
250 }
251
258 {
259 other.m_RelocationMock();
260 m_RelocationMock = std::move(other).m_RelocationMock;
261
262 return *this;
263 }
264
272 [[nodiscard]]
274 {
275 return m_RelocationMock.expect_call();
276 }
277
278 private:
279 Mock<void()> m_RelocationMock{};
280 };
281
282 template <typename T>
283 concept object_watcher = std::is_default_constructible_v<T>
284 && std::is_copy_constructible_v<T>
285 && std::is_copy_assignable_v<T>
286 && std::is_move_constructible_v<T>
287 && std::is_move_assignable_v<T>
288 && std::is_destructible_v<T>;
289
290 namespace detail
291 {
292 template <typename Base, typename... Watchers>
293 class CombinedWatchers
294 : public Watchers...
295 {
296 public:
297 ~CombinedWatchers() noexcept(std::is_nothrow_destructible_v<Base>) = default;
298
299 CombinedWatchers() = default;
300
301 CombinedWatchers(const CombinedWatchers&) = default;
302 CombinedWatchers& operator=(const CombinedWatchers&) = default;
303
304 CombinedWatchers(CombinedWatchers&& other) noexcept(std::is_nothrow_move_constructible_v<Base>) = default;
305 CombinedWatchers& operator=(CombinedWatchers&& other) noexcept(std::is_nothrow_move_assignable_v<Base>) = default;
306 };
307
308 template <typename Base, typename... Watchers>
309 class BasicWatched
310 : public CombinedWatchers<Base, Watchers...>,
311 public Base
312 {
313 public:
314 ~BasicWatched() = default;
315
316 using Base::Base;
317
318 BasicWatched(const BasicWatched&) = default;
319 BasicWatched& operator=(const BasicWatched&) = default;
320 BasicWatched(BasicWatched&&) = default;
321 BasicWatched& operator=(BasicWatched&&) = default;
322 };
323
324 template <satisfies<std::has_virtual_destructor> Base, typename... Watchers>
325 class BasicWatched<Base, Watchers...>
326 : public CombinedWatchers<Base, Watchers...>,
327 public Base
328 {
329 public:
330 ~BasicWatched() override = default;
331
332 using Base::Base;
333
334 BasicWatched(const BasicWatched&) = default;
335 BasicWatched& operator=(const BasicWatched&) = default;
336 BasicWatched(BasicWatched&&) = default;
337 BasicWatched& operator=(BasicWatched&&) = default;
338 };
339 }
340
394 template <typename Base, object_watcher... Watchers>
395 requires std::same_as<Base, std::remove_cvref_t<Base>>
397 : public detail::BasicWatched<Base, Watchers...>
398 {
399 using SuperT = detail::BasicWatched<Base, Watchers...>;
400
401 public:
402 ~Watched() = default;
403
404 using SuperT::SuperT;
405
406 Watched(const Watched&) = default;
407 Watched& operator=(const Watched&) = default;
408 Watched(Watched&&) = default;
409 Watched& operator=(Watched&&) = default;
410 };
411
415}
416
417#endif
A watcher type, which reports it's destructor calls.
Definition ObjectWatcher.hpp:57
LifetimeWatcher()=default
Defaulted default constructor.
~LifetimeWatcher() noexcept(false)
Destructor, which reports the call.
Definition ObjectWatcher.hpp:64
LifetimeWatcher & operator=(LifetimeWatcher &&)=default
Defaulted move-assignment-operator.
LifetimeWatcher(const LifetimeWatcher &other)
Copy-constructor.
Definition ObjectWatcher.hpp:91
LifetimeWatcher & operator=(const LifetimeWatcher &other)
Copy-assignment-operator.
Definition ObjectWatcher.hpp:111
LifetimeWatcher(LifetimeWatcher &&)=default
Defaulted move-constructor.
auto expect_destruct()
Begins a destruction-expectation construction.
Definition ObjectWatcher.hpp:150
A Mock type, which fully supports overload sets.
Definition Mock.hpp:390
A watcher type, which reports it's move-constructor and -assignment calls.
Definition ObjectWatcher.hpp:199
auto expect_relocate()
Begins a relocation-expectation construction.
Definition ObjectWatcher.hpp:273
RelocationWatcher(RelocationWatcher &&other) noexcept(false)
Move-constructor, which reports a relocation.
Definition ObjectWatcher.hpp:247
~RelocationWatcher()=default
Defaulted destructor.
RelocationWatcher(const RelocationWatcher &other)
Copy-constructor.
Definition ObjectWatcher.hpp:220
RelocationWatcher()=default
Defaulted default constructor.
RelocationWatcher & operator=(const RelocationWatcher &other)
Copy-assignment-operator.
Definition ObjectWatcher.hpp:232
RelocationWatcher & operator=(RelocationWatcher &&other) noexcept(false)
Move-assignment-operator, which reports a relocation.
Definition ObjectWatcher.hpp:257
CRTP-type, inheriting first from all Watchers and then Base, thus effectively couple them all togethe...
Definition ObjectWatcher.hpp:398
Watched(const Watched &)=default
Watched & operator=(const Watched &)=default
~Watched()=default
Watched(Watched &&)=default
Watched & operator=(Watched &&)=default
Definition ObjectWatcher.hpp:283
consteval auto once() noexcept
Specifies a times policy with both limits set to 1.
Definition ControlPolicy.hpp:340
Definition BoostTest.hpp:20