TLA Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/capy
8 : //
9 :
10 : #ifndef BOOST_CAPY_IO_RESULT_HPP
11 : #define BOOST_CAPY_IO_RESULT_HPP
12 :
13 : #include <boost/capy/detail/config.hpp>
14 : #include <system_error>
15 :
16 : #include <cstddef>
17 : #include <tuple>
18 : #include <type_traits>
19 : #include <utility>
20 :
21 : namespace boost {
22 : namespace capy {
23 :
24 : /** Result type for asynchronous I/O operations.
25 :
26 : This template provides a unified result type for async operations,
27 : always containing a `std::error_code` plus optional additional
28 : values. It supports structured bindings via the tuple protocol.
29 :
30 : @par Example
31 : @code
32 : auto [ec, n] = co_await s.read_some(buf);
33 : if (ec) { ... }
34 : @endcode
35 :
36 : @note Payload members are only meaningful when
37 : `ec` does not indicate an error.
38 :
39 : @tparam Ts Ordered payload types following the leading
40 : `std::error_code`.
41 : */
42 : template<class... Ts>
43 : struct [[nodiscard]] io_result
44 : {
45 : /// The error code from the operation.
46 : std::error_code ec;
47 :
48 : /// The payload values. Unspecified when `ec` is set.
49 : std::tuple<Ts...> values;
50 :
51 : /// Construct a default io_result.
52 HIT 754 : io_result() = default;
53 :
54 : /// Construct from an error code and payload values.
55 5918 : io_result(std::error_code ec_, Ts... ts)
56 5918 : : ec(ec_)
57 5581 : , values(std::move(ts)...)
58 : {
59 5918 : }
60 :
61 : template<std::size_t I>
62 : decltype(auto) get() & noexcept
63 : {
64 : static_assert(I < 1 + sizeof...(Ts), "index out of range");
65 : if constexpr (I == 0) return (ec);
66 : else return std::get<I - 1>(values);
67 : }
68 :
69 : template<std::size_t I>
70 : decltype(auto) get() const& noexcept
71 : {
72 : static_assert(I < 1 + sizeof...(Ts), "index out of range");
73 : if constexpr (I == 0) return (ec);
74 : else return std::get<I - 1>(values);
75 : }
76 :
77 : template<std::size_t I>
78 11593 : decltype(auto) get() && noexcept
79 : {
80 : static_assert(I < 1 + sizeof...(Ts), "index out of range");
81 6251 : if constexpr (I == 0) return std::move(ec);
82 5342 : else return std::get<I - 1>(std::move(values));
83 : }
84 : };
85 :
86 : #if !defined(BOOST_CAPY_MRDOCS)
87 : template<std::size_t I, class... Ts>
88 : decltype(auto) get(io_result<Ts...>& r) noexcept
89 : {
90 : return r.template get<I>();
91 : }
92 :
93 : template<std::size_t I, class... Ts>
94 : decltype(auto) get(io_result<Ts...> const& r) noexcept
95 : {
96 : return r.template get<I>();
97 : }
98 :
99 : template<std::size_t I, class... Ts>
100 : decltype(auto) get(io_result<Ts...>&& r) noexcept
101 : {
102 : return std::move(r).template get<I>();
103 : }
104 : #endif
105 :
106 : } // namespace capy
107 : } // namespace boost
108 :
109 : // Tuple protocol for structured bindings
110 : namespace std {
111 :
112 : template<class... Ts>
113 : struct tuple_size<boost::capy::io_result<Ts...>>
114 : : std::integral_constant<std::size_t, 1 + sizeof...(Ts)> {};
115 :
116 : template<class... Ts>
117 : struct tuple_element<0, boost::capy::io_result<Ts...>>
118 : {
119 : using type = std::error_code;
120 : };
121 :
122 : template<std::size_t I, class... Ts>
123 : struct tuple_element<I, boost::capy::io_result<Ts...>>
124 : {
125 : using type = std::tuple_element_t<I - 1, std::tuple<Ts...>>;
126 : };
127 :
128 : } // namespace std
129 :
130 : #endif // BOOST_CAPY_IO_RESULT_HPP
|