GCC Code Coverage Report


Directory: ./
File: include/CXXIter/src/IterValue.h
Date: 2023-01-04 16:32:12
Exec Total Coverage
Lines: 22 22 100.0%
Functions: 284 286 99.3%
Branches: 5 6 83.3%

Line Branch Exec Source
1 #pragma once
2
3 #include <type_traits>
4 #include <optional>
5
6 namespace CXXIter {
7
8 // ################################################################################################
9 // ITERATOR OPTIONAL (supports references)
10 // ################################################################################################
11
12 /**
13 * @brief Container that is used to pass elements through CXXIter's iterator pipelines.
14 * @details This is essentially a @c std::optional<> that also transparently supports references (in comparison
15 * to the original). This is achieved by wrapping reference types in a @c std::reference_wrapper<> before storing
16 * them in the internal @c std::optional<>.
17 */
18 template<typename TValue>
19 class IterValue {
20 private:
21 /** Owned (references removed) version of the type that is to be stored in this IterValue. */
22 using TValueDeref = std::remove_reference_t<TValue>;
23 using TValueStore = std::conditional_t<
24 std::is_reference_v<TValue>,
25 std::reference_wrapper<TValueDeref>,
26 TValue
27 >;
28
29 std::optional<TValueStore> inner;
30
31 public:
32 /** ctor */
33 1188 constexpr IterValue() noexcept {}
34 /** ctor */
35 2200 constexpr IterValue(TValue value) noexcept requires std::is_reference_v<TValue> : inner(value) {}
36 /** ctor */
37 2278 constexpr IterValue(const TValueDeref& value) noexcept(std::is_nothrow_copy_constructible_v<TValueDeref>)
38 2278 requires (!std::is_reference_v<TValue>) : inner(value) {}
39 /** ctor */
40 1506 constexpr IterValue(TValueDeref&& value) noexcept(std::is_nothrow_move_constructible_v<TValueDeref>)
41 1506 : inner(std::forward<TValueDeref>(value)) {}
42
43 /** Assignment from another IterValue instance. */
44 1034 constexpr IterValue& operator=(IterValue&& o) = default;
45 /** Assignment from another IterValue instance. */
46 2902 constexpr IterValue(IterValue&& o) noexcept(std::is_nothrow_move_constructible_v<TValueDeref>)
47 2902 : inner(std::move(o.inner)) {
48 2902 o.inner.reset();
49 2902 };
50
51 /** Assignment from an instance of the stored type. */
52 constexpr auto& operator=(TValueDeref&& o) {
53 this->inner = std::forward<decltype(o)>(o);
54 return *this;
55 }
56
57 /**
58 * @brief Get the contained value (if any).
59 * @throws If this is called when no value is contained.
60 * @return const reference to the contained value.
61 */
62 constexpr inline const TValueDeref& value() const { return inner.value(); }
63 /**
64 * @brief Get the contained value (if any).
65 * @throws If this is called when no value is contained.
66 * @return reference to the contained value.
67 */
68 6250 constexpr inline TValueDeref& value() { return inner.value(); }
69 /**
70 * @brief Get the contained value, or alternatively the given @p def if none is present.
71 * @param def Default value to return when this optional does not contain a value.
72 * @return const reference to the contained value (if any), or alternatively the given @p def value.
73 */
74 constexpr inline const TValueDeref& value_or(TValueDeref&& def) const noexcept { return inner.value_or(def); }
75 /**
76 * @brief Get the contained value, or alternatively the given @p def if none is present.
77 * @param def Default value to return when this optional does not contain a value.
78 * @return reference to the contained value (if any), or alternatively the given @p def value.
79 */
80 constexpr inline TValueDeref& value_or(TValueDeref&& def) noexcept { return inner.value_or(def); }
81
82 /**
83 * @brief Get whether this optional IteratorValue contains a value.
84 * @return @c true when this IterValue contains a value, @c false otherwise.
85 */
86 9742 constexpr bool has_value() const noexcept { return inner.has_value(); }
87
88 /**
89 * @brief Swap the values within this and another IterValue container.
90 * @param o Other IterValue container to swap contents with.
91 */
92 28 constexpr void swap(IterValue<TValue>& o) noexcept { inner.swap(o.inner); }
93
94 /**
95 * @brief Convert this IterValue to a @c std::optional<> on the owned (no-reference) type.
96 * @details If the contained value is a reference, the value will be copied into the returned @c std::optional<>.
97 * @return @c std::optional<> containing an owned version of the value contained by this IterValue.
98 */
99 34 constexpr std::optional<TValueStore> toStdOptional() noexcept {
100 34 return std::optional<TValueStore>(std::move(this->inner));
101 }
102 /**
103 * @brief Cast to @c std::optional<>.
104 */
105 constexpr operator std::optional<TValueStore>() noexcept { return toStdOptional(); }
106
107 /**
108 * @brief Map this IterValue's contained value (if any) to the requested new @p TOutValue type, using the given @p mapFn
109 * @tparam The requested output type for the mapping operation.
110 * @param mapFn Mapper function that takes this IterValue's contained value (if any) to map it to an instance of @p TOutValue
111 * @return A new IterValue containing the mapped value if this instance contained a value.
112 */
113 template<typename TOutValue, std::invocable<TValueDeref&&> TMapFn>
114 requires (!std::is_reference_v<TValue>)
115 108 constexpr IterValue<TOutValue> map(TMapFn mapFn) {
116
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 60 times.
108 if(!has_value()) { return {}; }
117
1/2
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
84 return mapFn(std::forward<TValueDeref>(value()));
118 }
119
120 /**
121 * @brief Map this IterValue's contained value (if any) to the requested new @p TOutValue type, using the given @p mapFn
122 * @tparam The requested output type for the mapping operation.
123 * @param mapFn Mapper function that takes this IterValue's contained value (if any) to map it to an instance of @p TOutValue
124 * @return A new IterValue containing the mapped value if this instance contained a value.
125 */
126 template<typename TOutValue, std::invocable<TValue> TMapFn>
127 requires std::is_reference_v<TValue>
128 454 constexpr IterValue<TOutValue> map(TMapFn mapFn) {
129
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
454 if(!this->has_value()) { return {}; }
130 383 return mapFn(this->value());
131 }
132 };
133
134 }
135