Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:38

0001 // Copyright (c) 2016-2023 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 template <class Char, class Traits, class T>
0122 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& in, io_fields_impl<const T&>&& ) {
0123     static_assert(sizeof(T) && false, "====================> Boost.PFR: Attempt to use istream operator on a boost::pfr::io_fields wrapped type T with const qualifier.");
0124     return in;
0125 }
0126 
0127 template <class Char, class Traits, class T>
0128 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& in, io_fields_impl<T>&& ) {
0129     static_assert(sizeof(T) && false, "====================> Boost.PFR: Attempt to use istream operator on a boost::pfr::io_fields wrapped temporary of type T.");
0130     return in;
0131 }
0132 
0133 } // namespace detail
0134 
0135 /// IO manipulator to read/write \aggregate `value` field-by-field.
0136 ///
0137 /// \b Example:
0138 /// \code
0139 ///     struct my_struct {
0140 ///         int i;
0141 ///         short s;
0142 ///     };
0143 ///
0144 ///     std::ostream& operator<<(std::ostream& os, const my_struct& x) {
0145 ///         return os << boost::pfr::io_fields(x);  // Equivalent to: os << "{ " << x.i << " ," <<  x.s << " }"
0146 ///     }
0147 ///
0148 ///     std::istream& operator>>(std::istream& is, my_struct& x) {
0149 ///         return is >> boost::pfr::io_fields(x);  // Equivalent to: is >> "{ " >> x.i >> " ," >>  x.s >> " }"
0150 ///     }
0151 /// \endcode
0152 ///
0153 /// Input and output streaming operators for `boost::pfr::io_fields` are symmetric, meaning that you get the original value by streaming it and
0154 /// reading back if each fields streaming operator is symmetric.
0155 ///
0156 /// \customio
0157 template <class T>
0158 auto io_fields(T&& value) noexcept {
0159     return detail::io_fields_impl<T>{std::forward<T>(value)};
0160 }
0161 
0162 }} // namespace boost::pfr
0163 
0164 #endif // BOOST_PFR_IO_FIELDS_HPP