LCOV - code coverage report
Current view: top level - boost/capy - type_traits.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 0.0 % 2 0
Test Date: 2026-01-23 10:17:56 Functions: 0.0 % 12 0

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot 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_TYPE_TRAITS_HPP
      11              : #define BOOST_CAPY_TYPE_TRAITS_HPP
      12              : 
      13              : #include <boost/capy/detail/config.hpp>
      14              : 
      15              : #include <concepts>
      16              : #include <cstddef>
      17              : #include <tuple>
      18              : #include <type_traits>
      19              : #include <utility>
      20              : 
      21              : namespace boost {
      22              : namespace capy {
      23              : 
      24              : /** Concept for types that support the tuple protocol.
      25              : 
      26              :     A type satisfies `has_tuple_protocol` if `std::tuple_size<T>`
      27              :     is a complete type with a `value` member.
      28              : 
      29              :     @tparam T The type to check.
      30              : */
      31              : template<typename T>
      32              : concept has_tuple_protocol = requires {
      33              :     std::tuple_size<std::remove_cvref_t<T>>::value;
      34              : };
      35              : 
      36              : namespace detail {
      37              : 
      38              : template<typename T, std::size_t... Is>
      39              : auto decomposed_types_impl(std::index_sequence<Is...>)
      40              :     -> std::tuple<std::tuple_element_t<Is, std::remove_cvref_t<T>>...>;
      41              : 
      42              : template<typename T>
      43              :     requires has_tuple_protocol<T>
      44              : using decomposed_types_t = decltype(
      45              :     decomposed_types_impl<T>(
      46              :         std::make_index_sequence<std::tuple_size_v<std::remove_cvref_t<T>>>{}
      47              :     )
      48              : );
      49              : 
      50              : template<typename T>
      51            0 : auto get_awaiter(T&& t)
      52              : {
      53              :     if constexpr (requires { std::forward<T>(t).operator co_await(); })
      54              :     {
      55              :         return std::forward<T>(t).operator co_await();
      56              :     }
      57              :     else if constexpr (requires { operator co_await(std::forward<T>(t)); })
      58              :     {
      59              :         return operator co_await(std::forward<T>(t));
      60              :     }
      61              :     else
      62              :     {
      63            0 :         return std::forward<T>(t);
      64              :     }
      65              : }
      66              : 
      67              : template<typename A>
      68              : using awaitable_return_t = decltype(
      69              :     get_awaiter(std::declval<A>()).await_resume()
      70              : );
      71              : 
      72              : } // namespace detail
      73              : 
      74              : /** Concept for types that decompose to a specific typelist.
      75              : 
      76              :     A type satisfies `decomposes_to` if it supports structured bindings
      77              :     via the tuple protocol and its element types match the specified
      78              :     typelist exactly.
      79              : 
      80              :     @tparam T The type to check.
      81              :     @tparam Types The expected element types after decomposition.
      82              : 
      83              :     @par Requirements
      84              :     @li `T` must satisfy the tuple protocol (`std::tuple_size`,
      85              :         `std::tuple_element`)
      86              :     @li The number of elements must equal `sizeof...(Types)`
      87              :     @li Each element type must match the corresponding type in `Types`
      88              : 
      89              :     @par Example
      90              :     @code
      91              :     static_assert(decomposes_to<std::pair<int, double>, int, double>);
      92              :     static_assert(decomposes_to<std::tuple<int, float, char>, int, float, char>);
      93              :     static_assert(decomposes_to<std::array<int, 3>, int, int, int>);
      94              : 
      95              :     // Constrain a function template
      96              :     template<typename T>
      97              :         requires decomposes_to<T, system::error_code, std::size_t>
      98              :     void process_result(T&& result)
      99              :     {
     100              :         auto [ec, n] = std::forward<T>(result);
     101              :         // ...
     102              :     }
     103              :     @endcode
     104              : 
     105              :     @note Plain aggregates without the tuple protocol are not supported.
     106              :         Use `std::pair`, `std::tuple`, `std::array`, or add the tuple
     107              :         protocol to your type.
     108              : */
     109              : template<typename T, typename... Types>
     110              : concept decomposes_to =
     111              :     has_tuple_protocol<T> &&
     112              :     std::same_as<
     113              :         detail::decomposed_types_t<T>,
     114              :         std::tuple<Types...>
     115              :     >;
     116              : 
     117              : /** Concept for awaitables whose return type decomposes to a specific typelist.
     118              : 
     119              :     A type satisfies `awaitable_decomposes_to` if it is an awaitable
     120              :     (has `await_resume`) and its return type satisfies @ref decomposes_to
     121              :     with the specified typelist.
     122              : 
     123              :     @tparam A The awaitable type.
     124              :     @tparam Types The expected element types after decomposition.
     125              : 
     126              :     @par Requirements
     127              :     @li `A` must be an awaitable (directly or via `operator co_await`)
     128              :     @li The return type of `await_resume()` must satisfy @ref decomposes_to
     129              :         with `Types...`
     130              : 
     131              :     @par Example
     132              :     @code
     133              :     // Constrain a function to accept only awaitables that return
     134              :     // a decomposable result of (error_code, size_t)
     135              :     template<typename A>
     136              :         requires awaitable_decomposes_to<A, system::error_code, std::size_t>
     137              :     task<void> process(A&& op)
     138              :     {
     139              :         auto [ec, n] = co_await std::forward<A>(op);
     140              :         if (ec)
     141              :             co_return;
     142              :         // process n bytes...
     143              :     }
     144              :     @endcode
     145              : 
     146              :     @see decomposes_to
     147              : */
     148              : template<typename A, typename... Types>
     149              : concept awaitable_decomposes_to = requires {
     150              :     typename detail::awaitable_return_t<A>;
     151              : } && decomposes_to<detail::awaitable_return_t<A>, Types...>;
     152              : 
     153              : } // namespace capy
     154              : } // namespace boost
     155              : 
     156              : #endif
        

Generated by: LCOV version 2.3