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 750 : io_result() = default;
53 :
54 : /// Construct from an error code and payload values.
55 5858 : io_result(std::error_code ec_, Ts... ts)
56 5858 : : ec(ec_)
57 5521 : , values(std::move(ts)...)
58 : {
59 5858 : }
60 :
61 : /// @cond
62 : template<std::size_t I>
63 : decltype(auto) get() & noexcept
64 : {
65 : static_assert(I < 1 + sizeof...(Ts), "index out of range");
66 : if constexpr (I == 0) return (ec);
67 : else return std::get<I - 1>(values);
68 : }
69 :
70 : template<std::size_t I>
71 : decltype(auto) get() const& noexcept
72 : {
73 : static_assert(I < 1 + sizeof...(Ts), "index out of range");
74 : if constexpr (I == 0) return (ec);
75 : else return std::get<I - 1>(values);
76 : }
77 :
78 : template<std::size_t I>
79 11471 : decltype(auto) get() && noexcept
80 : {
81 : static_assert(I < 1 + sizeof...(Ts), "index out of range");
82 6188 : if constexpr (I == 0) return std::move(ec);
83 5283 : else return std::get<I - 1>(std::move(values));
84 : }
85 : /// @endcond
86 : };
87 :
88 : /// @cond
89 : template<std::size_t I, class... Ts>
90 : decltype(auto) get(io_result<Ts...>& r) noexcept
91 : {
92 : return r.template get<I>();
93 : }
94 :
95 : template<std::size_t I, class... Ts>
96 : decltype(auto) get(io_result<Ts...> const& r) noexcept
97 : {
98 : return r.template get<I>();
99 : }
100 :
101 : template<std::size_t I, class... Ts>
102 : decltype(auto) get(io_result<Ts...>&& r) noexcept
103 : {
104 : return std::move(r).template get<I>();
105 : }
106 : /// @endcond
107 :
108 : } // namespace capy
109 : } // namespace boost
110 :
111 : // Tuple protocol for structured bindings
112 : namespace std {
113 :
114 : template<class... Ts>
115 : struct tuple_size<boost::capy::io_result<Ts...>>
116 : : std::integral_constant<std::size_t, 1 + sizeof...(Ts)> {};
117 :
118 : template<class... Ts>
119 : struct tuple_element<0, boost::capy::io_result<Ts...>>
120 : {
121 : using type = std::error_code;
122 : };
123 :
124 : template<std::size_t I, class... Ts>
125 : struct tuple_element<I, boost::capy::io_result<Ts...>>
126 : {
127 : using type = std::tuple_element_t<I - 1, std::tuple<Ts...>>;
128 : };
129 :
130 : } // namespace std
131 :
132 : #endif // BOOST_CAPY_IO_RESULT_HPP
|