Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:41:01

0001 // Copyright (c) 2016-2025 Antony Polukhin
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 
0007 #ifndef BOOST_PFR_IO_FIELDS_HPP
0008 #define BOOST_PFR_IO_FIELDS_HPP
0009 #pragma once
0010 
0011 #include <boost/pfr/detail/config.hpp>
0012 
0013 #include <boost/pfr/detail/core.hpp>
0014 
0015 #include <type_traits>
0016 #include <utility>      // metaprogramming stuff
0017 
0018 #include <boost/pfr/detail/sequence_tuple.hpp>
0019 #include <boost/pfr/detail/io.hpp>
0020 #include <boost/pfr/detail/make_integer_sequence.hpp>
0021 #include <boost/pfr/tuple_size.hpp>
0022 
0023 /// \file boost/pfr/io_fields.hpp
0024 /// Contains IO manipulator \forcedlink{io_fields} to read/write any \aggregate field-by-field.
0025 ///
0026 /// \b Example:
0027 /// \code
0028 ///     struct my_struct {
0029 ///         int i;
0030 ///         short s;
0031 ///     };
0032 ///
0033 ///     std::ostream& operator<<(std::ostream& os, const my_struct& x) {
0034 ///         return os << boost::pfr::io_fields(x);  // Equivalent to: os << "{ " << x.i << " ," <<  x.s << " }"
0035 ///     }
0036 ///
0037 ///     std::istream& operator>>(std::istream& is, my_struct& x) {
0038 ///         return is >> boost::pfr::io_fields(x);  // Equivalent to: is >> "{ " >> x.i >> " ," >>  x.s >> " }"
0039 ///     }
0040 /// \endcode
0041 ///
0042 /// \podops for other ways to define operators and more details.
0043 ///
0044 /// \b Synopsis:
0045 
0046 namespace boost { namespace pfr {
0047 
0048 namespace detail {
0049 
0050 template <class T>
0051 struct io_fields_impl {
0052     T value;
0053 };
0054 
0055 
0056 template <class Char, class Traits, class T>
0057 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& out, io_fields_impl<const T&>&& x) {
0058     const T& value = x.value;
0059     constexpr std::size_t fields_count_val = boost::pfr::detail::fields_count<T>();
0060     out << '{';
0061 #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
0062     detail::print_impl<0, fields_count_val>::print(out, detail::tie_as_tuple(value));
0063 #else
0064     ::boost::pfr::detail::for_each_field_dispatcher(
0065         value,
0066         [&out](const auto& val) {
0067             // We can not reuse `fields_count_val` in lambda because compilers had issues with
0068             // passing constexpr variables into lambdas. Computing is again is the most portable solution.
0069             constexpr std::size_t fields_count_val_lambda = boost::pfr::detail::fields_count<T>();
0070             detail::print_impl<0, fields_count_val_lambda>::print(out, val);
0071         },
0072         detail::make_index_sequence<fields_count_val>{}
0073     );
0074 #endif
0075     return out << '}';
0076 }
0077 
0078 
0079 template <class Char, class Traits, class T>
0080 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& out, io_fields_impl<T>&& x) {
0081     return out << io_fields_impl<const std::remove_reference_t<T>&>{x.value};
0082 }
0083 
0084 template <class Char, class Traits, class T>
0085 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& in, io_fields_impl<T&>&& x) {
0086     T& value = x.value;
0087     constexpr std::size_t fields_count_val = boost::pfr::detail::fields_count<T>();
0088 
0089     const auto prev_exceptions = in.exceptions();
0090     in.exceptions( typename std::basic_istream<Char, Traits>::iostate(0) );
0091     const auto prev_flags = in.flags( typename std::basic_istream<Char, Traits>::fmtflags(0) );
0092 
0093     char parenthis = {};
0094     in >> parenthis;
0095     if (parenthis != '{') in.setstate(std::basic_istream<Char, Traits>::failbit);
0096 
0097 #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
0098     detail::read_impl<0, fields_count_val>::read(in, detail::tie_as_tuple(value));
0099 #else
0100     ::boost::pfr::detail::for_each_field_dispatcher(
0101         value,
0102         [&in](const auto& val) {
0103             // We can not reuse `fields_count_val` in lambda because compilers had issues with
0104             // passing constexpr variables into lambdas. Computing is again is the most portable solution.
0105             constexpr std::size_t fields_count_val_lambda = boost::pfr::detail::fields_count<T>();
0106             detail::read_impl<0, fields_count_val_lambda>::read(in, val);
0107         },
0108         detail::make_index_sequence<fields_count_val>{}
0109     );
0110 #endif
0111 
0112     in >> parenthis;
0113     if (parenthis != '}') in.setstate(std::basic_istream<Char, Traits>::failbit);
0114 
0115     in.flags(prev_flags);
0116     in.exceptions(prev_exceptions);
0117 
0118     return in;
0119 }
0120 
0121 BOOST_PFR_BEGIN_MODULE_EXPORT
0122 
0123 template <class Char, class Traits, class T>
0124 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& in, io_fields_impl<const T&>&& ) {
0125     static_assert(sizeof(T) && false, "====================> Boost.PFR: Attempt to use istream operator on a boost::pfr::io_fields wrapped type T with const qualifier.");
0126     return in;
0127 }
0128 
0129 template <class Char, class Traits, class T>
0130 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& in, io_fields_impl<T>&& ) {
0131     static_assert(sizeof(T) && false, "====================> Boost.PFR: Attempt to use istream operator on a boost::pfr::io_fields wrapped temporary of type T.");
0132     return in;
0133 }
0134 
0135 BOOST_PFR_END_MODULE_EXPORT
0136 
0137 } // namespace detail
0138 
0139 BOOST_PFR_BEGIN_MODULE_EXPORT
0140 
0141 /// IO manipulator to read/write \aggregate `value` field-by-field.
0142 ///
0143 /// \b Example:
0144 /// \code
0145 ///     struct my_struct {
0146 ///         int i;
0147 ///         short s;
0148 ///     };
0149 ///
0150 ///     std::ostream& operator<<(std::ostream& os, const my_struct& x) {
0151 ///         return os << boost::pfr::io_fields(x);  // Equivalent to: os << "{ " << x.i << " ," <<  x.s << " }"
0152 ///     }
0153 ///
0154 ///     std::istream& operator>>(std::istream& is, my_struct& x) {
0155 ///         return is >> boost::pfr::io_fields(x);  // Equivalent to: is >> "{ " >> x.i >> " ," >>  x.s >> " }"
0156 ///     }
0157 /// \endcode
0158 ///
0159 /// Input and output streaming operators for `boost::pfr::io_fields` are symmetric, meaning that you get the original value by streaming it and
0160 /// reading back if each fields streaming operator is symmetric.
0161 ///
0162 /// \customio
0163 template <class T>
0164 auto io_fields(T&& value) noexcept {
0165     return detail::io_fields_impl<T>{std::forward<T>(value)};
0166 }
0167 
0168 BOOST_PFR_END_MODULE_EXPORT
0169 
0170 }} // namespace boost::pfr
0171 
0172 #endif // BOOST_PFR_IO_FIELDS_HPP