GCC Code Coverage Report


Directory: ./
File: SharedCloneable.hpp
Date: 2026-03-21 20:51:59
Exec Total Coverage
Lines: 9 10 90.0%
Functions: 10 10 100.0%
Branches: 4 8 50.0%

Line Branch Exec Source
1 #pragma once
2 #include "SharedObject.hpp"
3 #include "compat/gsl14.hpp"
4
5 // [The ‘clonable’ pattern](https://herbsutter.com/2019/10/03/gotw-ish-solution-the-clonable-pattern/)
6 // [Polymorphic clones in modern C++](https://www.fluentcpp.com/2017/09/08/make-polymorphic-copy-modern-cpp/)
7 // [How to Return a Smart Pointer AND Use Covariance](https://www.fluentcpp.com/2017/09/12/how-to-return-a-smart-pointer-and-use-covariance/)
8
9 template <typename Derived, typename Base = SharedObject>
10 class SharedCloneable : public Base {
11 public:
12 std::shared_ptr<Derived> clone() const;
13 12 ~SharedCloneable() noexcept override = default;
14
15 protected:
16 using Base::Base; // Inherit all constructors from Base.
17 6 SharedCloneable() noexcept = default;
18 6 SharedCloneable(const SharedCloneable&) = default;
19 SharedCloneable(SharedCloneable&&) noexcept = delete;
20 SharedCloneable& operator=(const SharedCloneable&) = delete;
21 SharedCloneable& operator=(SharedCloneable&&) noexcept = delete;
22
23 private:
24 // NOLINTNEXTLINE(*-explicit-virtual-functions, *-use-override)
25 [[nodiscard]] virtual std::shared_ptr<SharedObject> cloneImpl() const;
26 };
27
28 template <typename Derived, typename Base>
29 4 std::shared_ptr<Derived> SharedCloneable<Derived, Base>::clone() const {
30
1/2
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
8 auto result = std::static_pointer_cast<Derived>(std::move(cloneImpl()));
31
32 // Derived class must override cloneImpl!
33
2/4
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
4 Ensures(typeid(*result) == typeid(*this));
34 static_assert(
35 not(std::is_copy_constructible<Derived>::value
36 || std::is_move_constructible<Derived>::value
37 || std::is_copy_assignable<Derived>::value
38 || std::is_move_assignable<Derived>::value),
39 "Derived class must not be copy/move constructible/assignable!");
40
41 4 return result;
42 }
43
44 template <typename Derived, typename Base>
45 4 std::shared_ptr<SharedObject> SharedCloneable<Derived, Base>::cloneImpl() const {
46
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 return create<Derived>(static_cast<const Derived&>(*this));
47 }
48