Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:39:23

0001 //
0002 // Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_MYSQL_SEQUENCE_HPP
0009 #define BOOST_MYSQL_SEQUENCE_HPP
0010 
0011 #include <boost/mysql/detail/sequence.hpp>
0012 
0013 #ifdef BOOST_MYSQL_HAS_CONCEPTS
0014 #include <concepts>
0015 #endif
0016 
0017 namespace boost {
0018 namespace mysql {
0019 
0020 /**
0021  * \brief The return type of \ref sequence.
0022  * \details
0023  * Contains a range, a formatter function, and a glue string.
0024  * This type satisfies the `Formattable` concept.
0025  *
0026  * When formatted, \ref format_function is invoked for each element
0027  * in \ref range. The string \ref glue is output raw (as per \ref format_context_base::append_raw)
0028  * between consecutive invocations of the formatter function, generating an effect
0029  * similar to `std::ranges::views::join`.
0030  *
0031  * Don't instantiate this struct directly - use \ref sequence, instead.
0032  *
0033  * \par Type requirements
0034  *
0035  *   - Expressions `std::begin(range)` and `std::end(range)` should return an input iterator/sentinel
0036  *     pair that can be compared for (in)equality.
0037  *   - The expression `static_cast<const FormatFn&>(fn)(* std::begin(range), ctx)`
0038  *     should be well formed, with `ctx` begin a `format_context_base&`.
0039  */
0040 template <class Range, class FormatFn>
0041 #if defined(BOOST_MYSQL_HAS_CONCEPTS)
0042     requires detail::format_fn_for_range<FormatFn, Range>
0043 #endif
0044 struct format_sequence
0045 {
0046     /// The range to format.
0047     Range range;
0048 
0049     /// The format function to apply to each element in the range.
0050     FormatFn format_function;
0051 
0052     /// The string to output between range elements.
0053     constant_string_view glue;
0054 };
0055 
0056 /**
0057  * \brief The type of range produced by \ref sequence.
0058  * \details
0059  * This type trait can be used to obtain the range type produced
0060  * by calling \ref sequence. This type is used as the `Range` template
0061  * parameter in \ref format_sequence.
0062  *
0063  * By default, \ref sequence copies its input range, unless
0064  * using `std::ref`. C arrays are copied into `std::array` objects.
0065  * This type trait accounts these transformations.
0066  *
0067  * Formally, given the input range type `T` (which can be a reference with cv-qualifiers):
0068  *
0069  *  - If `T` is a C array or a reference to one (as per `std::is_array`),
0070  *    and the array elements' type is `U`, yields `std::array<std::remove_cv_t<U>, N>`.
0071  *  - If `T` is a `std::reference_wrapper<U>` object, or a reference to one,
0072  *    yields `U&`.
0073  *  - Otherwise, yields `std::remove_cvref_t<T>`.
0074  *
0075  * Examples:
0076  *
0077  *  - `sequence_range_t<const std::vector<int>&>` is `std::vector<int>`.
0078  *  - `sequence_range_t<std::reference_wrapper<std::vector<int>>>` is `std::vector<int>&`.
0079  *  - `sequence_range_t<std::reference_wrapper<const std::vector<int>>>` is `const std::vector<int>&`.
0080  *  - `sequence_range_t<int(&)[4]>` is `std::array<int, 4>`.
0081  */
0082 template <class T>
0083 using sequence_range_t =
0084 #ifdef BOOST_MYSQL_DOXYGEN
0085     __see_below__
0086 #else
0087     typename detail::sequence_range_type<T>::type;
0088 #endif
0089     ;
0090 
0091 /**
0092  * \brief Creates an object that, when formatted, applies a per-element function to a range.
0093  * \details
0094  * Objects returned by this function satisfy `Formattable`.
0095  * Formatting such objects invokes `fn` for each element
0096  * in `range`, outputting `glue` between invocations.
0097  * This generates an effect similar to `std::ranges::views::join`.
0098  *
0099  * By default, this function creates an owning object by decay-copying `range` into it.
0100  * C arrays are copied into `std::array` objects. This behavior can be disabled
0101  * by passing `std::reference_wrapper` objects, which are converted to references
0102  * (as `std::make_tuple` does). The \ref sequence_range_t
0103  * type trait accounts for these transformations.
0104  *
0105  * Formally:
0106  *
0107  *   - If `Range` is a (possibly cv-qualified) C array reference (as per `std::is_array<Range>`),
0108  *     and the array has `N` elements of type `U`, the output range type is
0109  *     `std::array<std::remove_cv< U >, N>`, and the range is created as if `std::to_array` was called.
0110  *   - If `Range` is a `std::reference_wrapper< U >` object, or a reference to one,
0111  *     the output range type is `U&`. This effectively disables copying the input range.
0112  *     The resulting object will be a view type, and the caller is responsible for lifetime management.
0113  *   - Otherwise, the output range type is `std::remove_cvref_t<Range>`, and it will be
0114  *     created by forwarding the passed `range`.
0115  *
0116  * `FormatFn` is always decay-copied into the resulting object.
0117  *
0118  * The glue string is always stored as a view, as it should usually point to a compile-time constant.
0119  *
0120  * \par Type requirements
0121  *
0122  * The resulting range and format function should be compatible, and any required
0123  * copy/move operations should be well defined. Formally:
0124  *
0125  *   - `std::decay_t<FormatFn>` should be a formatter function compatible with
0126  *     the elements of the output range. See \ref format_sequence for the formal requirements.
0127  *   - If `Range` is a `std::reference_wrapper< U >`, or a reference to one,
0128  *     no further requirements are placed on `U`.
0129  *   - If `Range` is a lvalue reference to a C array, its elements should be copy-constructible
0130  *     (as per `std::to_array` requirements).
0131  *   - If `Range` is a rvalue reference to a C array, its elements should be move-constructible
0132  *     (as per `std::to_array` requirements).
0133  *   - Performing a decay-copy of `FormatFn` should be well defined.
0134  *
0135  * \par Exception safety
0136  * Basic guarantee. Propagates any exception thrown when constructing the output
0137  * range and format function.
0138  */
0139 template <class Range, class FormatFn>
0140 #if defined(BOOST_MYSQL_HAS_CONCEPTS)
0141     requires std::constructible_from<typename std::decay<FormatFn>::type, FormatFn&&>
0142 #endif
0143 format_sequence<sequence_range_t<Range>, typename std::decay<FormatFn>::type> sequence(
0144     Range&& range,
0145     FormatFn&& fn,
0146     constant_string_view glue = ", "
0147 )
0148 
0149 {
0150     return {detail::cast_range(std::forward<Range>(range)), std::forward<FormatFn>(fn), glue};
0151 }
0152 
0153 template <class Range, class FormatFn>
0154 struct formatter<format_sequence<Range, FormatFn>>
0155 {
0156     const char* parse(const char* begin, const char*) { return begin; }
0157 
0158     void format(format_sequence<Range, FormatFn>& value, format_context_base& ctx) const
0159     {
0160         detail::do_format_sequence(value.range, value.format_function, value.glue, ctx);
0161     }
0162 
0163     void format(const format_sequence<Range, FormatFn>& value, format_context_base& ctx) const
0164     {
0165         detail::do_format_sequence(value.range, value.format_function, value.glue, ctx);
0166     }
0167 };
0168 
0169 }  // namespace mysql
0170 }  // namespace boost
0171 
0172 #endif