include/boost/capy/io_result.hpp

100.0% Lines (8/0/8) 100.0% List of functions (34/0/34)
io_result.hpp
f(x) Functions (34)
Function Calls Lines Blocks
boost::capy::io_result<>::io_result() :57 54x 100.0% 100.0% boost::capy::io_result<int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool>::io_result() :57 1x 100.0% 100.0% boost::capy::io_result<unsigned long>::io_result() :57 75x 100.0% 100.0% boost::capy::io_result<(anonymous namespace)::parallel::page_data>::io_result(std::error_code, (anonymous namespace)::parallel::page_data) :65 1x 100.0% 100.0% boost::capy::io_result<>::io_result(std::error_code) :65 228x 100.0% 100.0% boost::capy::io_result<boost::capy::(anonymous namespace)::throwing_move_payload>::io_result(std::error_code, boost::capy::(anonymous namespace)::throwing_move_payload) :65 1x 100.0% 100.0% boost::capy::io_result<boost::capy::async_mutex::lock_guard>::io_result(std::error_code, boost::capy::async_mutex::lock_guard) :65 4x 100.0% 100.0% boost::capy::io_result<int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::io_result(std::error_code, int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) :65 1x 100.0% 100.0% boost::capy::io_result<int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool>::io_result(std::error_code, int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool) :65 1x 100.0% 100.0% boost::capy::io_result<int, double>::io_result(std::error_code, int, double) :65 4x 100.0% 100.0% boost::capy::io_result<int, int, int>::io_result(std::error_code, int, int, int) :65 3x 100.0% 100.0% boost::capy::io_result<int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::io_result(std::error_code, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) :65 2x 100.0% 100.0% boost::capy::io_result<int, int>::io_result(std::error_code, int, int) :65 3x 100.0% 100.0% boost::capy::io_result<int, std::tuple<>, int>::io_result(std::error_code, int, std::tuple<>, int) :65 2x 100.0% 100.0% boost::capy::io_result<int>::io_result(std::error_code, int) :65 23x 100.0% 100.0% boost::capy::io_result<long long, long long, long long, long long>::io_result(std::error_code, long long, long long, long long, long long) :65 1x 100.0% 100.0% boost::capy::io_result<long long>::io_result(std::error_code, long long) :65 4x 100.0% 100.0% boost::capy::io_result<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::io_result(std::error_code, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) :65 15x 100.0% 100.0% boost::capy::io_result<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::io_result(std::error_code, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) :65 1x 100.0% 100.0% boost::capy::io_result<std::error_code>::io_result(std::error_code, std::error_code) :65 1x 100.0% 100.0% boost::capy::io_result<std::tuple<>, std::tuple<> >::io_result(std::error_code, std::tuple<>, std::tuple<>) :65 22x 100.0% 100.0% boost::capy::io_result<std::tuple<>, std::tuple<>, std::tuple<> >::io_result(std::error_code, std::tuple<>, std::tuple<>, std::tuple<>) :65 1x 100.0% 100.0% boost::capy::io_result<std::vector<int, std::allocator<int> > >::io_result(std::error_code, std::vector<int, std::allocator<int> >) :65 1x 100.0% 100.0% boost::capy::io_result<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::io_result(std::error_code, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) :65 1x 100.0% 100.0% boost::capy::io_result<std::vector<unsigned long, std::allocator<unsigned long> > >::io_result(std::error_code, std::vector<unsigned long, std::allocator<unsigned long> >) :65 9x 100.0% 100.0% boost::capy::io_result<std::vector<unsigned long, std::allocator<unsigned long> >, unsigned long>::io_result(std::error_code, std::vector<unsigned long, std::allocator<unsigned long> >, unsigned long) :65 1x 100.0% 100.0% boost::capy::io_result<unsigned long, int>::io_result(std::error_code, unsigned long, int) :65 1x 100.0% 100.0% boost::capy::io_result<unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::io_result(std::error_code, unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) :65 1x 100.0% 100.0% boost::capy::io_result<unsigned long, std::tuple<> >::io_result(std::error_code, unsigned long, std::tuple<>) :65 1x 100.0% 100.0% boost::capy::io_result<unsigned long, std::tuple<unsigned long, int> >::io_result(std::error_code, unsigned long, std::tuple<unsigned long, int>) :65 1x 100.0% 100.0% boost::capy::io_result<unsigned long, unsigned long, unsigned long>::io_result(std::error_code, unsigned long, unsigned long, unsigned long) :65 2x 100.0% 100.0% boost::capy::io_result<unsigned long, unsigned long>::io_result(std::error_code, unsigned long, unsigned long) :65 7x 100.0% 100.0% boost::capy::io_result<unsigned long>::io_result(std::error_code, unsigned long) :65 1640x 100.0% 100.0% decltype(auto) boost::capy::io_result<>::get<0ul>() && :119 156x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2026 Michael Vandeberg
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/capy
9 //
10
11 #ifndef BOOST_CAPY_IO_RESULT_HPP
12 #define BOOST_CAPY_IO_RESULT_HPP
13
14 #include <boost/capy/detail/config.hpp>
15 #include <system_error>
16
17 #include <cstddef>
18 #include <tuple>
19 #include <type_traits>
20 #include <utility>
21
22 namespace boost {
23 namespace capy {
24
25 /** Bundles an error code with optional payload values, exposed via the tuple protocol.
26
27 This template provides a unified result type for async operations,
28 always containing a `std::error_code` plus optional additional
29 values. It supports structured bindings via the tuple protocol.
30
31 @par Example
32 @code
33 auto [ec, n] = co_await s.read_some(buf);
34 if (ec) { ... }
35 @endcode
36
37 @note Whether the payload is meaningful when `ec` is set is
38 defined by the operation that produced the result. Many I/O
39 operations report a meaningful partial result alongside `ec`
40 (for example, the number of bytes transferred before the
41 condition, as with EOF). Others leave it unspecified.
42
43 @tparam Ts Ordered payload types following the leading
44 `std::error_code`.
45 */
46 template<class... Ts>
47 struct [[nodiscard]] io_result
48 {
49 /// The error code from the operation.
50 std::error_code ec;
51
52 /// The payload values. Their meaning when `ec` is set is defined
53 /// by the producing operation (see the class note).
54 std::tuple<Ts...> values;
55
56 /// Construct a default io_result.
57 130x io_result() = default;
58
59 /** Construct from an error code and payload values.
60
61 @param ec_ The error code for the operation.
62
63 @param ts The payload values, in declaration order.
64 */
65 1983x io_result(std::error_code ec_, Ts... ts)
66 1983x : ec(ec_)
67 1755x , values(std::move(ts)...)
68 {
69 1983x }
70
71 /** Return the `I`-th element of the tuple protocol.
72
73 Index 0 is @ref ec; index `I` for `I > 0` is the `I - 1`-th
74 payload value. This is the accessor structured bindings use.
75
76 @tparam I The element index. Must be less than
77 `1 + sizeof...(Ts)`.
78
79 @return A reference to the element.
80 */
81 template<std::size_t I>
82 decltype(auto) get() & noexcept
83 {
84 static_assert(I < 1 + sizeof...(Ts), "index out of range");
85 if constexpr (I == 0) return (ec);
86 else return std::get<I - 1>(values);
87 }
88
89 /** Return the `I`-th element of the tuple protocol.
90
91 Index 0 is @ref ec; index `I` for `I > 0` is the `I - 1`-th
92 payload value. This is the accessor structured bindings use.
93
94 @tparam I The element index. Must be less than
95 `1 + sizeof...(Ts)`.
96
97 @return A const reference to the element.
98 */
99 template<std::size_t I>
100 decltype(auto) get() const& noexcept
101 {
102 static_assert(I < 1 + sizeof...(Ts), "index out of range");
103 if constexpr (I == 0) return (ec);
104 else return std::get<I - 1>(values);
105 }
106
107 /** Return the `I`-th element of the tuple protocol, moved.
108
109 Index 0 is @ref ec; index `I` for `I > 0` is the `I - 1`-th
110 payload value.
111
112 @tparam I The element index. Must be less than
113 `1 + sizeof...(Ts)`.
114
115 @return An rvalue reference to the element, suitable for moving
116 out of the result.
117 */
118 template<std::size_t I>
119 3116x decltype(auto) get() && noexcept
120 {
121 static_assert(I < 1 + sizeof...(Ts), "index out of range");
122 1644x if constexpr (I == 0) return std::move(ec);
123 1472x else return std::get<I - 1>(std::move(values));
124 }
125 };
126
127 /** Return the `I`-th element of the tuple protocol.
128
129 @tparam I The element index. Must be less than
130 `1 + sizeof...(Ts)`.
131
132 @param r The result to access.
133
134 @return A reference to the element.
135 */
136 template<std::size_t I, class... Ts>
137 decltype(auto) get(io_result<Ts...>& r) noexcept
138 {
139 return r.template get<I>();
140 }
141
142 /** Return the `I`-th element of the tuple protocol.
143
144 @tparam I The element index. Must be less than
145 `1 + sizeof...(Ts)`.
146
147 @param r The result to access.
148
149 @return A const reference to the element.
150 */
151 template<std::size_t I, class... Ts>
152 decltype(auto) get(io_result<Ts...> const& r) noexcept
153 {
154 return r.template get<I>();
155 }
156
157 /** Return the `I`-th element of the tuple protocol, moved.
158
159 @tparam I The element index. Must be less than
160 `1 + sizeof...(Ts)`.
161
162 @param r The result to access.
163
164 @return An rvalue reference to the element, suitable for moving out
165 of `r`.
166 */
167 template<std::size_t I, class... Ts>
168 decltype(auto) get(io_result<Ts...>&& r) noexcept
169 {
170 return std::move(r).template get<I>();
171 }
172
173 } // namespace capy
174 } // namespace boost
175
176 // Tuple protocol for structured bindings
177 namespace std {
178
179 template<class... Ts>
180 struct tuple_size<boost::capy::io_result<Ts...>>
181 : std::integral_constant<std::size_t, 1 + sizeof...(Ts)> {};
182
183 template<class... Ts>
184 struct tuple_element<0, boost::capy::io_result<Ts...>>
185 {
186 using type = std::error_code;
187 };
188
189 template<std::size_t I, class... Ts>
190 struct tuple_element<I, boost::capy::io_result<Ts...>>
191 {
192 using type = std::tuple_element_t<I - 1, std::tuple<Ts...>>;
193 };
194
195 } // namespace std
196
197 #endif // BOOST_CAPY_IO_RESULT_HPP
198