0.00% Lines (0/0) 0.00% Functions (0/0)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/capy 7   // Official repository: https://github.com/cppalliance/capy
8   // 8   //
9   9  
10   #ifndef BOOST_CAPY_IO_RESULT_HPP 10   #ifndef BOOST_CAPY_IO_RESULT_HPP
11   #define BOOST_CAPY_IO_RESULT_HPP 11   #define BOOST_CAPY_IO_RESULT_HPP
12   12  
13   #include <boost/capy/detail/config.hpp> 13   #include <boost/capy/detail/config.hpp>
14   #include <system_error> 14   #include <system_error>
15 - #include <cstddef>  
16   15  
17   #include <tuple> 16   #include <tuple>
18 - #include <utility>  
19   #include <type_traits> 17   #include <type_traits>
20   18  
21   namespace boost { 19   namespace boost {
22   namespace capy { 20   namespace capy {
23   21  
24   /** Result type for asynchronous I/O operations. 22   /** Result type for asynchronous I/O operations.
25   23  
26 - This template provides a unified result type for async operations, 24 + This alias provides a unified result type for async operations,
27   always containing a `std::error_code` plus optional additional 25   always containing a `std::error_code` plus optional additional
28 - values. It supports structured bindings via the tuple protocol. 26 + values. Because it is a `std::tuple`, results interoperate with
  27 + the entire standard tuple API: structured bindings, `std::tie`,
  28 + `std::apply`, `std::get`, `std::tuple_cat`, comparisons, and
  29 + tuple assignment.
29   30  
30   @par Example 31   @par Example
31   @code 32   @code
32   auto [ec, n] = co_await s.read_some(buf); 33   auto [ec, n] = co_await s.read_some(buf);
33   if (ec) { ... } 34   if (ec) { ... }
34   @endcode 35   @endcode
35   36  
36 - @note Whether the payload is meaningful when `ec` is set is 37 + `std::tie` rebinds into existing variables without introducing
37 - defined by the operation that produced the result. Many I/O 38 + new bindings:
38 - operations report a meaningful partial result alongside `ec` 39 + @code
39 - (for example, the number of bytes transferred before the 40 + std::error_code ec;
40 - condition, as with EOF); others leave it unspecified. 41 + std::size_t n = 0;
  42 + std::tie(ec, n) = co_await s.read_some(buf);
  43 + @endcode
  44 +
  45 + @note Whether the payload is meaningful when the error code is
  46 + set is defined by the operation that produced the result.
  47 + Many I/O operations report a meaningful partial result
  48 + alongside the error (for example, the number of bytes
  49 + transferred before the condition, as with EOF); others
  50 + leave it unspecified.
41   51  
42   @tparam Ts Ordered payload types following the leading 52   @tparam Ts Ordered payload types following the leading
43   `std::error_code`. 53   `std::error_code`.
44   */ 54   */
45   template<class... Ts> 55   template<class... Ts>
46 - struct [[nodiscard]] io_result 56 + using io_result = std::tuple<std::error_code, Ts...>;
47 - {  
48 - /// The error code from the operation.  
49 - std::error_code ec;  
50 -  
51 - /// The payload values. Their meaning when `ec` is set is defined  
52 - /// by the producing operation (see the class note).  
53 - std::tuple<Ts...> values;  
54 -  
55 - /// Construct a default io_result.  
DCB 56 - 130 io_result() = default;  
57 -  
58 - /// Construct from an error code and payload values.  
DCB 59 - 1986 io_result(std::error_code ec_, Ts... ts)  
DCB 60 - 1986 : ec(ec_)  
DCB 61 - 1755 , values(std::move(ts)...)  
62 - {  
DCB 63 - 1986 }  
64 -  
65 - /// @cond  
66 - template<std::size_t I>  
67 - decltype(auto) get() & noexcept  
68 - {  
69 - static_assert(I < 1 + sizeof...(Ts), "index out of range");  
70 - if constexpr (I == 0) return (ec);  
71 - else return std::get<I - 1>(values);  
72 - }  
73   57  
74 - template<std::size_t I> 58 + namespace detail {
75 - decltype(auto) get() const& noexcept  
76 - {  
77 - static_assert(I < 1 + sizeof...(Ts), "index out of range");  
78 - if constexpr (I == 0) return (ec);  
79 - else return std::get<I - 1>(values);  
80 - }  
81   59  
82 - template<std::size_t I> 60 + // Outcomes are structural, not nominal: any std::tuple whose first
ECB 83 - 3119 decltype(auto) get() && noexcept 61 + // element is error_code is an io_result, regardless of how the
84 - { 62 + // producing operation spelled it.
85 - static_assert(I < 1 + sizeof...(Ts), "index out of range"); 63 + template<class T>
ECB 86 - 1647 if constexpr (I == 0) return std::move(ec); 64 + struct is_io_result : std::false_type {};
DCB 87 - 1472 else return std::get<I - 1>(std::move(values));  
88 - }  
89 - /// @endcond  
90 - };  
91   65  
92 - /// @cond 66 + template<class... Ts>
93 - template<std::size_t I, class... Ts> 67 + struct is_io_result<std::tuple<std::error_code, Ts...>>
94 - decltype(auto) get(io_result<Ts...>& r) noexcept 68 + : std::true_type {};
95 - {  
96 - return r.template get<I>();  
97 - }  
98   69  
99 - template<std::size_t I, class... Ts> 70 + template<class T>
100 - decltype(auto) get(io_result<Ts...> const& r) noexcept 71 + inline constexpr bool is_io_result_v = is_io_result<T>::value;
101 - {  
102 - return r.template get<I>();  
103 - }  
104   72  
105 - template<std::size_t I, class... Ts> 73 + } // namespace detail
106 - decltype(auto) get(io_result<Ts...>&& r) noexcept  
107 - {  
108 - return std::move(r).template get<I>();  
109 - }  
110 - /// @endcond  
111   74  
112   } // namespace capy 75   } // namespace capy
113 -  
114 - // Tuple protocol for structured bindings  
115 - namespace std {  
116 -  
117 - template<class... Ts>  
118 - struct tuple_size<boost::capy::io_result<Ts...>>  
119 - : std::integral_constant<std::size_t, 1 + sizeof...(Ts)> {};  
120 -  
121 - template<class... Ts>  
122 - struct tuple_element<0, boost::capy::io_result<Ts...>>  
123 - {  
124 - using type = std::error_code;  
125 - };  
126 -  
127 - template<std::size_t I, class... Ts>  
128 - struct tuple_element<I, boost::capy::io_result<Ts...>>  
129 - {  
130 - using type = std::tuple_element_t<I - 1, std::tuple<Ts...>>;  
131 - };  
132 -  
133 - } // namespace std  
134   } // namespace boost 76   } // namespace boost
135   77  
136   #endif // BOOST_CAPY_IO_RESULT_HPP 78   #endif // BOOST_CAPY_IO_RESULT_HPP