mimic++ v4
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
159 return m_DestructionMock->expect_call()
160 and expect::once(); // prevent further times specifications
161 }
162
163 private:
164 bool m_HasDestructExpectation{};
165 std::unique_ptr<Mock<void()>> m_DestructionMock{
166 std::make_unique<Mock<void()>>()
167 };
168 };
169
201 {
202 public:
207
211 [[nodiscard]]
212 RelocationWatcher() = default;
213
221 [[nodiscard]]
222 RelocationWatcher([[maybe_unused]] const RelocationWatcher& other)
224 {
225 }
226
234 RelocationWatcher& operator =([[maybe_unused]] const RelocationWatcher& other)
235 {
236 // explicitly circumvent default construct and assign, because that would
237 // involve the move-assignment.
238 m_RelocationMock = Mock<void()>{};
239
240 return *this;
241 }
242
248 [[nodiscard]]
249 RelocationWatcher(RelocationWatcher&& other) noexcept(false)
250 {
251 *this = std::move(other);
252 }
253
260 {
261 other.m_RelocationMock();
262 m_RelocationMock = std::move(other).m_RelocationMock;
263
264 return *this;
265 }
266
274 [[nodiscard]]
276 {
277 return m_RelocationMock.expect_call();
278 }
279
280 private:
281 Mock<void()> m_RelocationMock{};
282 };
283
284 template <typename T>
285 concept object_watcher = std::is_default_constructible_v<T>
286 && std::is_copy_constructible_v<T>
287 && std::is_copy_assignable_v<T>
288 && std::is_move_constructible_v<T>
289 && std::is_move_assignable_v<T>
290 && std::is_destructible_v<T>;
291
292 namespace detail
293 {
294 template <typename Base, typename... Watchers>
295 class CombinedWatchers
296 : public Watchers...
297 {
298 public:
299 ~CombinedWatchers() noexcept(std::is_nothrow_destructible_v<Base>) = default;
300
301 CombinedWatchers() = default;
302
303 CombinedWatchers(const CombinedWatchers&) = default;
304 CombinedWatchers& operator =(const CombinedWatchers&) = default;
305
306 CombinedWatchers(CombinedWatchers&& other) noexcept(std::is_nothrow_move_constructible_v<Base>) = default;
307 CombinedWatchers& operator =(CombinedWatchers&& other) noexcept(std::is_nothrow_move_assignable_v<Base>) = default;
308 };
309
310 template <typename Base, typename... Watchers>
311 class BasicWatched
312 : public CombinedWatchers<Base, Watchers...>,
313 public Base
314 {
315 public:
316 ~BasicWatched() = default;
317
318 using Base::Base;
319
320 BasicWatched(const BasicWatched&) = default;
321 BasicWatched& operator =(const BasicWatched&) = default;
322 BasicWatched(BasicWatched&&) = default;
323 BasicWatched& operator =(BasicWatched&&) = default;
324 };
325
326 template <satisfies<std::has_virtual_destructor> Base, typename... Watchers>
327 class BasicWatched<Base, Watchers...>
328 : public CombinedWatchers<Base, Watchers...>,
329 public Base
330 {
331 public:
332 ~BasicWatched() override = default;
333
334 using Base::Base;
335
336 BasicWatched(const BasicWatched&) = default;
337 BasicWatched& operator =(const BasicWatched&) = default;
338 BasicWatched(BasicWatched&&) = default;
339 BasicWatched& operator =(BasicWatched&&) = default;
340 };
341 }
342
396 template <typename Base, object_watcher... Watchers>
397 requires std::same_as<Base, std::remove_cvref_t<Base>>
399 : public detail::BasicWatched<Base, Watchers...>
400 {
401 using SuperT = detail::BasicWatched<Base, Watchers...>;
402
403 public:
404 ~Watched() = default;
405
406 using SuperT::SuperT;
407
408 Watched(const Watched&) = default;
409 Watched& operator =(const Watched&) = default;
410 Watched(Watched&&) = default;
412 };
413
417}
418
419#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(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:600
A watcher type, which reports it's move-constructor and -assignment calls.
Definition ObjectWatcher.hpp:201
auto expect_relocate()
Begins a relocation-expectation construction.
Definition ObjectWatcher.hpp:275
RelocationWatcher(RelocationWatcher &&other) noexcept(false)
Move-constructor, which reports a relocation.
Definition ObjectWatcher.hpp:249
~RelocationWatcher()=default
Defaulted destructor.
RelocationWatcher(const RelocationWatcher &other)
Copy-constructor.
Definition ObjectWatcher.hpp:222
RelocationWatcher()=default
Defaulted default constructor.
RelocationWatcher & operator=(const RelocationWatcher &other)
Copy-assignment-operator.
Definition ObjectWatcher.hpp:234
CRTP-type, inheriting first from all Watchers and then Base, thus effectively couple them all togethe...
Definition ObjectWatcher.hpp:400
Watched(const Watched &)=default
Watched & operator=(const Watched &)=default
~Watched()=default
Watched(Watched &&)=default
Definition ObjectWatcher.hpp:285
consteval auto once() noexcept
Specifies a times policy with both limits set to 1.
Definition ControlPolicy.hpp:356
Definition BoostTest.hpp:20