-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathlegacy_output_iterator.cppm
More file actions
94 lines (78 loc) · 3.07 KB
/
legacy_output_iterator.cppm
File metadata and controls
94 lines (78 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
export module iterator:legacy_output_iterator;
import concepts;
import :legacy_iterator;
import std;
template <typename T>
using base_it = zero::iterator::legacy::iterator<
std::output_iterator_tag, void, void, void>;
export namespace zero::iterator::legacy
{
/**
* @brief A generic implementation of an output_iterator
*/
template <typename T>
struct output_iter : base_it<T> {
private:
T *_ptr;
// TODO move this to the details partition
/**
* @details A proxy helper class for the output_iter class.
*
* The output_iter_proxy class is used to facilitate assignment operations with an
* output iterator while preventing the user from reading from it
*/
template <typename Z>
struct output_iter_proxy {
output_iter<Z> &_iter;
constexpr explicit output_iter_proxy(output_iter<Z> &iter) noexcept : _iter(iter) {}
template <typename U>
constexpr auto operator=(const U &val) -> output_iter_proxy& {
_iter = val;
return *this;
}
/**
* @brief Assigns a value to the output iterator.
*
* @tparam U The type of the value being assigned.
* @param val The value being assigned to the output iterator.
* @return output_iter_proxy& A reference to the output_iter_proxy object.
*/
template <typename U>
operator const U&() const = delete;
};
public:
constexpr output_iter<T>() noexcept = default; // Left defaulted and not deleted because the legacy implementation
constexpr explicit output_iter(T& elem) noexcept : _ptr(&elem) {}
constexpr output_iter<T>(const output_iter<T> &other) = default;
constexpr output_iter<T>(output_iter<T> &&other) noexcept = default;
template <typename U>
constexpr auto operator=(const U &val) -> output_iter & {
if constexpr (std::is_base_of_v<std::ostream, std::remove_reference_t<T>>)
*_ptr << val;
else if constexpr (zero::concepts::has_push_back<std::remove_reference_t<T>, const U &>)
_ptr->push_back(val);
else
*_ptr++ = val;
return *this;
}
[[nodiscard]]
constexpr auto operator*() -> output_iter_proxy<T> {
return output_iter_proxy<T>(*this);
}
constexpr auto operator->() const -> output_iter* = delete;
constexpr auto operator++() noexcept -> output_iter<T>& {
return *this;
}
constexpr auto operator++(int) noexcept -> output_iter<T> {
return *this;
}
[[nodiscard]]
constexpr friend auto operator==(const output_iter& lhs, const output_iter& rhs) noexcept -> bool {
return lhs._ptr == rhs._ptr;
}
[[nodiscard]]
constexpr friend auto operator!=(const output_iter& lhs, const output_iter& rhs) noexcept -> bool {
return lhs != rhs;
}
};
}