From 2dbbcb17fec6ae2c240827798c50fb93f1418a8a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 15:35:20 -0700 Subject: [PATCH 01/11] Use friendship for `n + InternalIteratorType`. (`_Span_iterator` already did.) --- stl/inc/array | 25 ++++++++++------------- stl/inc/deque | 53 +++++++++++++++++++++---------------------------- stl/inc/vector | 52 +++++++++++++++++++++--------------------------- stl/inc/xstring | 40 +++++++++++++++++-------------------- 4 files changed, 75 insertions(+), 95 deletions(-) diff --git a/stl/inc/array b/stl/inc/array index 60cd6270c3..9af9b30ab6 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -253,6 +253,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND _CONSTEXPR17 _Array_const_iterator operator+( + const ptrdiff_t _Off, _Array_const_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + #if !_HAS_CXX20 _NODISCARD _CONSTEXPR17 bool operator!=(const _Array_const_iterator& _Right) const noexcept { return !(*this == _Right); @@ -281,13 +287,6 @@ constexpr void _Verify_range( } #endif // _ITERATOR_DEBUG_LEVEL != 0 -template -_NODISCARD _CONSTEXPR17 _Array_const_iterator<_Ty, _Size> operator+( - const ptrdiff_t _Off, _Array_const_iterator<_Ty, _Size> _Next) noexcept { - _Next += _Off; - return _Next; -} - #if _HAS_CXX20 template struct pointer_traits<_Array_const_iterator<_Ty, _Size>> { @@ -362,6 +361,11 @@ public: return _Tmp; } + _NODISCARD_FRIEND _CONSTEXPR17 _Array_iterator operator+(const ptrdiff_t _Off, _Array_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + _CONSTEXPR17 _Array_iterator& operator-=(const ptrdiff_t _Off) noexcept { _Mybase::operator-=(_Off); return *this; @@ -386,13 +390,6 @@ public: } }; -template -_NODISCARD _CONSTEXPR17 _Array_iterator<_Ty, _Size> operator+( - const ptrdiff_t _Off, _Array_iterator<_Ty, _Size> _Next) noexcept { - _Next += _Off; - return _Next; -} - #if _HAS_CXX20 template struct pointer_traits<_Array_iterator<_Ty, _Size>> { diff --git a/stl/inc/deque b/stl/inc/deque index 9fbbcee9df..dc2457bc32 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -85,6 +85,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND _Deque_unchecked_const_iterator operator+( + const difference_type _Off, _Deque_unchecked_const_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + _Deque_unchecked_const_iterator& operator-=(const difference_type _Off) noexcept { _Myoff -= _Off; return *this; @@ -142,14 +148,6 @@ public: _Size_type _Myoff; // offset of element in deque }; -template -_NODISCARD _Deque_unchecked_const_iterator<_Mydeque> operator+( - typename _Deque_unchecked_const_iterator<_Mydeque>::difference_type _Off, - _Deque_unchecked_const_iterator<_Mydeque> _Next) noexcept { - _Next += _Off; - return _Next; -} - template class _Deque_unchecked_iterator : public _Deque_unchecked_const_iterator<_Mydeque> { private: @@ -207,6 +205,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND _Deque_unchecked_iterator operator+( + const difference_type _Off, _Deque_unchecked_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + _Deque_unchecked_iterator& operator-=(const difference_type _Off) noexcept { _Mybase::operator-=(_Off); return *this; @@ -227,14 +231,6 @@ public: } }; -template -_NODISCARD _Deque_unchecked_iterator<_Mydeque> operator+( - typename _Deque_unchecked_iterator<_Mydeque>::difference_type _Off, - _Deque_unchecked_iterator<_Mydeque> _Next) noexcept { - _Next += _Off; - return _Next; -} - template class _Deque_const_iterator : public _Iterator_base12 { private: @@ -332,6 +328,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND _Deque_const_iterator operator+( + const difference_type _Off, _Deque_const_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + _Deque_const_iterator& operator-=(const difference_type _Off) noexcept { return *this += -_Off; } @@ -430,13 +432,6 @@ public: _Size_type _Myoff; // offset of element in deque }; -template -_NODISCARD _Deque_const_iterator<_Mydeque> operator+( - typename _Deque_const_iterator<_Mydeque>::difference_type _Off, _Deque_const_iterator<_Mydeque> _Next) noexcept { - _Next += _Off; - return _Next; -} - template class _Deque_iterator : public _Deque_const_iterator<_Mydeque> { private: @@ -495,6 +490,11 @@ public: return _Tmp; } + _NODISCARD_FRIEND _Deque_iterator operator+(const difference_type _Off, _Deque_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + _Deque_iterator& operator-=(const difference_type _Off) noexcept { _Mybase::operator-=(_Off); return *this; @@ -519,13 +519,6 @@ public: } }; -template -_NODISCARD _Deque_iterator<_Mydeque> operator+( - typename _Deque_iterator<_Mydeque>::difference_type _Off, _Deque_iterator<_Mydeque> _Next) noexcept { - _Next += _Off; - return _Next; -} - template struct _Deque_iter_types { diff --git a/stl/inc/vector b/stl/inc/vector index de2e3a19c1..efa9abcf35 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -126,6 +126,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND _CONSTEXPR20 _Vector_const_iterator operator+( + const difference_type _Off, _Vector_const_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + _CONSTEXPR20 _Vector_const_iterator& operator-=(const difference_type _Off) noexcept { return *this += -_Off; } @@ -208,13 +214,6 @@ public: _Tptr _Ptr; // pointer to element in vector }; -template -_NODISCARD _CONSTEXPR20 _Vector_const_iterator<_Myvec> operator+( - typename _Vector_const_iterator<_Myvec>::difference_type _Off, _Vector_const_iterator<_Myvec> _Next) noexcept { - _Next += _Off; - return _Next; -} - #if _HAS_CXX20 template struct pointer_traits<_Vector_const_iterator<_Myvec>> { @@ -306,6 +305,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND _CONSTEXPR20 _Vector_iterator operator+( + const difference_type _Off, _Vector_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + _CONSTEXPR20 _Vector_iterator& operator-=(const difference_type _Off) noexcept { _Mybase::operator-=(_Off); return *this; @@ -330,13 +335,6 @@ public: } }; -template -_NODISCARD _CONSTEXPR20 _Vector_iterator<_Myvec> operator+( - typename _Vector_iterator<_Myvec>::difference_type _Off, _Vector_iterator<_Myvec> _Next) noexcept { - _Next += _Off; - return _Next; -} - #if _HAS_CXX20 template struct pointer_traits<_Vector_iterator<_Myvec>> { @@ -2461,6 +2459,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND _CONSTEXPR20 _Vb_const_iterator operator+( + const difference_type _Off, _Vb_const_iterator _Right) noexcept { + _Right += _Off; + return _Right; + } + _CONSTEXPR20 _Vb_const_iterator& operator-=(const difference_type _Off) noexcept { return *this += -_Off; } @@ -2567,14 +2571,6 @@ public: } }; -template -_NODISCARD _CONSTEXPR20 _Vb_const_iterator<_Alvbase_wrapped> operator+( - typename _Vb_const_iterator<_Alvbase_wrapped>::difference_type _Off, - _Vb_const_iterator<_Alvbase_wrapped> _Right) noexcept { - _Right += _Off; - return _Right; -} - template class _Vb_iterator : public _Vb_const_iterator<_Alvbase_wrapped> { public: @@ -2637,6 +2633,11 @@ public: return _Tmp; } + _NODISCARD_FRIEND _CONSTEXPR20 _Vb_iterator operator+(const difference_type _Off, _Vb_iterator _Right) noexcept { + _Right += _Off; + return _Right; + } + _CONSTEXPR20 _Vb_iterator& operator-=(const difference_type _Off) noexcept { _Mybase::operator-=(_Off); return *this; @@ -2657,13 +2658,6 @@ public: using _Prevent_inheriting_unwrap = _Vb_iterator; }; -template -_NODISCARD _CONSTEXPR20 _Vb_iterator<_Alvbase_wrapped> operator+( - typename _Vb_iterator<_Alvbase_wrapped>::difference_type _Off, _Vb_iterator<_Alvbase_wrapped> _Right) noexcept { - _Right += _Off; - return _Right; -} - template class _Vb_val : public _Container_base { public: diff --git a/stl/inc/xstring b/stl/inc/xstring index ff946f56a5..53b697b27f 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -1043,6 +1043,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND constexpr _String_view_iterator operator+( + const difference_type _Off, _String_view_iterator _Right) noexcept { + _Right += _Off; + return _Right; + } + constexpr _String_view_iterator& operator-=(const difference_type _Off) noexcept { #if _ITERATOR_DEBUG_LEVEL >= 1 if (_Off != 0) { @@ -1172,14 +1178,6 @@ private: #endif // _ITERATOR_DEBUG_LEVEL }; -template -_NODISCARD constexpr _String_view_iterator<_Traits> operator+( - const typename _String_view_iterator<_Traits>::difference_type _Off, - _String_view_iterator<_Traits> _Right) noexcept { - _Right += _Off; - return _Right; -} - #if _HAS_CXX20 template struct pointer_traits<_String_view_iterator<_Traits>> { @@ -1988,6 +1986,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND _CONSTEXPR20 _String_const_iterator operator+( + const difference_type _Off, _String_const_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + _CONSTEXPR20 _String_const_iterator& operator-=(const difference_type _Off) noexcept { return *this += -_Off; } @@ -2071,13 +2075,6 @@ public: pointer _Ptr; // pointer to element in string }; -template -_NODISCARD _CONSTEXPR20 _String_const_iterator<_Mystr> operator+( - typename _String_const_iterator<_Mystr>::difference_type _Off, _String_const_iterator<_Mystr> _Next) noexcept { - _Next += _Off; - return _Next; -} - #if _HAS_CXX20 template struct pointer_traits<_String_const_iterator<_Mystr>> { @@ -2166,6 +2163,12 @@ public: return _Tmp; } + _NODISCARD_FRIEND _CONSTEXPR20 _String_iterator operator+( + const difference_type _Off, _String_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + _CONSTEXPR20 _String_iterator& operator-=(const difference_type _Off) noexcept { _Mybase::operator-=(_Off); return *this; @@ -2190,13 +2193,6 @@ public: } }; -template -_NODISCARD _CONSTEXPR20 _String_iterator<_Mystr> operator+( - typename _String_iterator<_Mystr>::difference_type _Off, _String_iterator<_Mystr> _Next) noexcept { - _Next += _Off; - return _Next; -} - #if _HAS_CXX20 template struct pointer_traits<_String_iterator<_Mystr>> { From 9b6935970188b325598e07bcc23a96bf4349dc26 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:33:48 -0700 Subject: [PATCH 02/11] Use friendship for _Time_parse_iomanip_c_str, _Time_parse_iomanip. --- stl/inc/chrono | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index e41c17fd17..ad81de20af 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -4493,6 +4493,12 @@ namespace chrono { _Time_parse_iomanip_c_str(_Time_parse_iomanip_c_str&&) = delete; + friend basic_istream<_CharT, _Traits>& operator>>( + basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip_c_str&& _Tpi) { + from_stream(_Is, _Tpi._Fmt, _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); // intentional ADL + return _Is; + } + const _CharT* _Fmt; _Parsable& _Tp; basic_string<_CharT, _Traits, _Alloc>* _Abbrev; @@ -4507,6 +4513,12 @@ namespace chrono { _Time_parse_iomanip(_Time_parse_iomanip&&) = delete; + friend basic_istream<_CharT, _Traits>& operator>>( + basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip&& _Tpi) { + from_stream(_Is, _Tpi._Fmt.c_str(), _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); // intentional ADL + return _Is; + } + const basic_string<_CharT, _Traits, _Alloc>& _Fmt; _Parsable& _Tp; basic_string<_CharT, _Traits, _Alloc>* _Abbrev; @@ -4568,21 +4580,6 @@ namespace chrono { basic_string<_CharT, _Traits, _Alloc>& _Abbrev, minutes& _Offset) { return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev), &_Offset}; } - - template - basic_istream<_CharT, _Traits>& operator>>( - basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip_c_str<_CharT, _Traits, _Alloc, _Parsable>&& _Tpi) { - from_stream(_Is, _Tpi._Fmt, _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); // intentional ADL - return _Is; - } - - template - basic_istream<_CharT, _Traits>& operator>>( - basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip<_CharT, _Traits, _Alloc, _Parsable>&& _Tpi) { - from_stream(_Is, _Tpi._Fmt.c_str(), _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); // intentional ADL - return _Is; - } - } // namespace chrono #ifdef __cpp_lib_format From ccb3a0abd60b25dd9f00acf1d2f249c2e452853a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:34:11 -0700 Subject: [PATCH 03/11] Use friendship for _Local_time_format_t. --- stl/inc/chrono | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index ad81de20af..56fb46d3da 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -4823,6 +4823,14 @@ namespace chrono { local_time<_Duration> _Time; const string* _Abbrev = nullptr; const seconds* _Offset_sec = nullptr; + + template + friend basic_ostream<_CharT, _Traits>& operator<<( + basic_ostream<_CharT, _Traits>& _Os, const _Local_time_format_t& _Val) { + // Doesn't appear in the Standard, but allowed by N4885 [global.functions]/2. + // Implements N4885 [time.zone.zonedtime.nonmembers]/2 for zoned_time. + return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%F %T %Z}"), _Val); + } }; template @@ -5155,14 +5163,6 @@ namespace chrono { return _Os << sys_time<_Duration>{_Val.time_since_epoch()}; } - template - basic_ostream<_CharT, _Traits>& operator<<( - basic_ostream<_CharT, _Traits>& _Os, const _Local_time_format_t<_Duration>& _Val) { - // Doesn't appear in the Standard, but allowed by N4885 [global.functions]/2. - // Implements N4885 [time.zone.zonedtime.nonmembers]/2 for zoned_time. - return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%F %T %Z}"), _Val); - } - template basic_ostream<_CharT, _Traits>& operator<<( basic_ostream<_CharT, _Traits>& _Os, const zoned_time<_Duration, _TimeZonePtr>& _Val) { From c3edfd59c2df154ea54d144d0225cfe683c0fc5f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:28:56 -0700 Subject: [PATCH 04/11] Use friendship for _Fillobj. --- stl/inc/iomanip | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/stl/inc/iomanip b/stl/inc/iomanip index 4ce454f86e..cec89202d7 100644 --- a/stl/inc/iomanip +++ b/stl/inc/iomanip @@ -25,6 +25,24 @@ template struct _Fillobj { // store fill character _Fillobj(_Elem _Ch) : _Fill(_Ch) {} + template + friend basic_istream<_Elem2, _Traits>& operator>>(basic_istream<_Elem2, _Traits>& _Istr, const _Fillobj& _Manip) { + // set fill character in input stream + static_assert(is_same_v<_Elem, _Elem2>, "wrong character type for setfill"); + + _Istr.fill(_Manip._Fill); + return _Istr; + } + + template + friend basic_ostream<_Elem2, _Traits>& operator<<(basic_ostream<_Elem2, _Traits>& _Ostr, const _Fillobj& _Manip) { + // set fill character in output stream + static_assert(is_same_v<_Elem, _Elem2>, "wrong character type for setfill"); + + _Ostr.fill(_Manip._Fill); + return _Ostr; + } + _Elem _Fill; // the fill character }; @@ -33,24 +51,6 @@ _NODISCARD _Fillobj<_Elem> setfill(_Elem _Ch) { return _Fillobj<_Elem>(_Ch); } -template -basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, - const _Fillobj<_Elem2>& _Manip) { // set fill character in input stream - static_assert(is_same_v<_Elem, _Elem2>, "wrong character type for setfill"); - - _Istr.fill(_Manip._Fill); - return _Istr; -} - -template -basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, - const _Fillobj<_Elem2>& _Manip) { // set fill character in output stream - static_assert(is_same_v<_Elem, _Elem2>, "wrong character type for setfill"); - - _Ostr.fill(_Manip._Fill); - return _Ostr; -} - template struct _Monobj { // store reference to monetary amount _Monobj(_Money& _Val_arg, bool _Intl_arg) : _Val(_Val_arg), _Intl(_Intl_arg) {} From 4296557e7ed2c2bc29ab05cf585d57b1ef63f1d2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:29:35 -0700 Subject: [PATCH 05/11] Use friendship for _Monobj. --- stl/inc/iomanip | 88 ++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/stl/inc/iomanip b/stl/inc/iomanip index cec89202d7..6574e3e667 100644 --- a/stl/inc/iomanip +++ b/stl/inc/iomanip @@ -55,6 +55,50 @@ template struct _Monobj { // store reference to monetary amount _Monobj(_Money& _Val_arg, bool _Intl_arg) : _Val(_Val_arg), _Intl(_Intl_arg) {} + template + friend basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, const _Monobj& _Manip) { + // get monetary amount from input stream + using _Myis = basic_istream<_Elem, _Traits>; + using _Iter = istreambuf_iterator<_Elem, _Traits>; + using _Mymget = money_get<_Elem, _Iter>; + + ios_base::iostate _State = ios_base::goodbit; + const typename _Myis::sentry _Ok(_Istr); + + if (_Ok) { // state okay, extract monetary amount + const _Mymget& _Mget_fac = _STD use_facet<_Mymget>(_Istr.getloc()); + _TRY_IO_BEGIN + _Mget_fac.get(_Iter(_Istr.rdbuf()), _Iter(nullptr), _Manip._Intl, _Istr, _State, _Manip._Val); + _CATCH_IO_(ios_base, _Istr) + } + + _Istr.setstate(_State); + return _Istr; + } + + template + friend basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, const _Monobj& _Manip) { + // put monetary amount to output stream + using _Myos = basic_ostream<_Elem, _Traits>; + using _Iter = ostreambuf_iterator<_Elem, _Traits>; + using _Mymput = money_put<_Elem, _Iter>; + + ios_base::iostate _State = ios_base::goodbit; + const typename _Myos::sentry _Ok(_Ostr); + + if (_Ok) { // state okay, insert monetary amount + const _Mymput& _Mput_fac = _STD use_facet<_Mymput>(_Ostr.getloc()); + _TRY_IO_BEGIN + if (_Mput_fac.put(_Iter(_Ostr.rdbuf()), _Manip._Intl, _Ostr, _Ostr.fill(), _Manip._Val).failed()) { + _State |= ios_base::badbit; + } + _CATCH_IO_(ios_base, _Ostr) + } + + _Ostr.setstate(_State); + return _Ostr; + } + _Money& _Val; // the monetary amount reference bool _Intl; // international flag }; @@ -64,55 +108,11 @@ _NODISCARD _Monobj<_Money> get_money(_Money& _Val_arg, bool _Intl_arg = false) { return _Monobj<_Money>(_Val_arg, _Intl_arg); } -template -basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, - const _Monobj<_Money>& _Manip) { // get monetary amount from input stream - using _Myis = basic_istream<_Elem, _Traits>; - using _Iter = istreambuf_iterator<_Elem, _Traits>; - using _Mymget = money_get<_Elem, _Iter>; - - ios_base::iostate _State = ios_base::goodbit; - const typename _Myis::sentry _Ok(_Istr); - - if (_Ok) { // state okay, extract monetary amount - const _Mymget& _Mget_fac = _STD use_facet<_Mymget>(_Istr.getloc()); - _TRY_IO_BEGIN - _Mget_fac.get(_Iter(_Istr.rdbuf()), _Iter(nullptr), _Manip._Intl, _Istr, _State, _Manip._Val); - _CATCH_IO_(ios_base, _Istr) - } - - _Istr.setstate(_State); - return _Istr; -} - template _NODISCARD _Monobj put_money(const _Money& _Val_arg, bool _Intl_arg = false) { return _Monobj(_Val_arg, _Intl_arg); } -template -basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, - const _Monobj<_Money>& _Manip) { // put monetary amount to output stream - using _Myos = basic_ostream<_Elem, _Traits>; - using _Iter = ostreambuf_iterator<_Elem, _Traits>; - using _Mymput = money_put<_Elem, _Iter>; - - ios_base::iostate _State = ios_base::goodbit; - const typename _Myos::sentry _Ok(_Ostr); - - if (_Ok) { // state okay, insert monetary amount - const _Mymput& _Mput_fac = _STD use_facet<_Mymput>(_Ostr.getloc()); - _TRY_IO_BEGIN - if (_Mput_fac.put(_Iter(_Ostr.rdbuf()), _Manip._Intl, _Ostr, _Ostr.fill(), _Manip._Val).failed()) { - _State |= ios_base::badbit; - } - _CATCH_IO_(ios_base, _Ostr) - } - - _Ostr.setstate(_State); - return _Ostr; -} - template struct _Timeobj { // store reference to tm object and format _Timeobj(_Ptr _Tptr_arg, const _Elem* _Fmt_arg) : _Tptr(_Tptr_arg), _Fmtfirst(_Fmt_arg) { From 9b147dfa495deaf556c78bc262a074f0730df0fd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:31:27 -0700 Subject: [PATCH 06/11] Use friendship for _Timeobj. --- stl/inc/iomanip | 97 +++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/stl/inc/iomanip b/stl/inc/iomanip index 6574e3e667..bd5c6f1e17 100644 --- a/stl/inc/iomanip +++ b/stl/inc/iomanip @@ -120,6 +120,55 @@ struct _Timeobj { // store reference to tm object and format } } + template + friend basic_istream<_Elem2, _Traits>& operator>>(basic_istream<_Elem2, _Traits>& _Istr, const _Timeobj& _Manip) { + // get time information from input stream + static_assert(is_same_v<_Elem, _Elem2>, "wrong character type for get_time"); + + using _Myis = basic_istream<_Elem, _Traits>; + using _Iter = istreambuf_iterator<_Elem, _Traits>; + using _Mytget = time_get<_Elem, _Iter>; + + ios_base::iostate _State = ios_base::goodbit; + const typename _Myis::sentry _Ok(_Istr); + + if (_Ok) { // state okay, extract time amounts + const _Mytget& _Tget_fac = _STD use_facet<_Mytget>(_Istr.getloc()); + _TRY_IO_BEGIN + _Tget_fac.get( + _Iter(_Istr.rdbuf()), _Iter(nullptr), _Istr, _State, _Manip._Tptr, _Manip._Fmtfirst, _Manip._Fmtlast); + _CATCH_IO_(ios_base, _Istr) + } + + _Istr.setstate(_State); + return _Istr; + } + + template + friend basic_ostream<_Elem2, _Traits>& operator<<(basic_ostream<_Elem2, _Traits>& _Ostr, const _Timeobj& _Manip) { + // put time information to output stream + static_assert(is_same_v<_Elem, _Elem2>, "wrong character type for put_time"); + + using _Myos = basic_ostream<_Elem, _Traits>; + using _Iter = ostreambuf_iterator<_Elem, _Traits>; + using _Mytput = time_put<_Elem, _Iter>; + + const typename _Myos::sentry _Ok(_Ostr); + + if (_Ok) { // state okay, insert monetary amount + const _Mytput& _Tput_fac = _STD use_facet<_Mytput>(_Ostr.getloc()); + _TRY_IO_BEGIN + if (_Tput_fac + .put(_Iter(_Ostr.rdbuf()), _Ostr, _Ostr.fill(), _Manip._Tptr, _Manip._Fmtfirst, _Manip._Fmtlast) + .failed()) { + _Ostr.setstate(ios_base::badbit); + } + _CATCH_IO_(ios_base, _Ostr) + } + + return _Ostr; + } + _Ptr _Tptr; // the tm struct pointer const _Elem* _Fmtfirst; // format string start const _Elem* _Fmtlast; // format string end @@ -130,59 +179,11 @@ _NODISCARD _Timeobj<_Elem, tm*> get_time(tm* _Tptr_arg, const _Elem* _Fmt_arg) { return _Timeobj<_Elem, tm*>(_Tptr_arg, _Fmt_arg); } -template -basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, - const _Timeobj<_Elem2, tm*>& _Manip) { // get time information from input stream - using _Myis = basic_istream<_Elem, _Traits>; - using _Iter = istreambuf_iterator<_Elem, _Traits>; - using _Mytget = time_get<_Elem2, _Iter>; - - static_assert(is_same_v<_Elem, _Elem2>, "wrong character type for get_time"); - - ios_base::iostate _State = ios_base::goodbit; - const typename _Myis::sentry _Ok(_Istr); - - if (_Ok) { // state okay, extract time amounts - const _Mytget& _Tget_fac = _STD use_facet<_Mytget>(_Istr.getloc()); - _TRY_IO_BEGIN - _Tget_fac.get( - _Iter(_Istr.rdbuf()), _Iter(nullptr), _Istr, _State, _Manip._Tptr, _Manip._Fmtfirst, _Manip._Fmtlast); - _CATCH_IO_(ios_base, _Istr) - } - - _Istr.setstate(_State); - return _Istr; -} - template _NODISCARD _Timeobj<_Elem, const tm*> put_time(const tm* _Tptr_arg, const _Elem* _Fmt_arg) { return _Timeobj<_Elem, const tm*>(_Tptr_arg, _Fmt_arg); } -template -basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, - const _Timeobj<_Elem2, const tm*>& _Manip) { // put time information to output stream - using _Myos = basic_ostream<_Elem, _Traits>; - using _Iter = ostreambuf_iterator<_Elem, _Traits>; - using _Mytput = time_put<_Elem2, _Iter>; - - static_assert(is_same_v<_Elem, _Elem2>, "wrong character type for put_time"); - - const typename _Myos::sentry _Ok(_Ostr); - - if (_Ok) { // state okay, insert monetary amount - const _Mytput& _Tput_fac = _STD use_facet<_Mytput>(_Ostr.getloc()); - _TRY_IO_BEGIN - if (_Tput_fac.put(_Iter(_Ostr.rdbuf()), _Ostr, _Ostr.fill(), _Manip._Tptr, _Manip._Fmtfirst, _Manip._Fmtlast) - .failed()) { - _Ostr.setstate(ios_base::badbit); - } - _CATCH_IO_(ios_base, _Ostr) - } - - return _Ostr; -} - template struct _Quote_in { // store reference to string using _Mystr = basic_string<_Elem, _Traits, _Alloc>; From b044d6c8e2ea6897f397cb39bee1a90f333b8f58 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:31:58 -0700 Subject: [PATCH 07/11] Use friendship for _Smanip. --- stl/inc/iomanip | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/stl/inc/iomanip b/stl/inc/iomanip index bd5c6f1e17..851adaf457 100644 --- a/stl/inc/iomanip +++ b/stl/inc/iomanip @@ -384,24 +384,24 @@ template struct _Smanip { // store function pointer and argument value _Smanip(void(__cdecl* _Left)(ios_base&, _Arg), _Arg _Val) : _Pfun(_Left), _Manarg(_Val) {} + template + friend basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, const _Smanip& _Manip) { + // extract by calling function with input stream and argument + (*_Manip._Pfun)(_Istr, _Manip._Manarg); + return _Istr; + } + + template + friend basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, const _Smanip& _Manip) { + // insert by calling function with output stream and argument + (*_Manip._Pfun)(_Ostr, _Manip._Manarg); + return _Ostr; + } + void(__cdecl* _Pfun)(ios_base&, _Arg); // the function pointer _Arg _Manarg; // the argument value }; -template -basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, - const _Smanip<_Arg>& _Manip) { // extract by calling function with input stream and argument - (*_Manip._Pfun)(_Istr, _Manip._Manarg); - return _Istr; -} - -template -basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, - const _Smanip<_Arg>& _Manip) { // insert by calling function with output stream and argument - (*_Manip._Pfun)(_Ostr, _Manip._Manarg); - return _Ostr; -} - _NODISCARD _MRTIMP2 _Smanip __cdecl resetiosflags(ios_base::fmtflags); _NODISCARD _MRTIMP2 _Smanip __cdecl setiosflags(ios_base::fmtflags); _NODISCARD _MRTIMP2 _Smanip __cdecl setbase(int); From 1e84f5d8b3c794be987787411643c46f492b9622 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:35:01 -0700 Subject: [PATCH 08/11] Move _Quote_out before _Quote_in. --- stl/inc/iomanip | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/stl/inc/iomanip b/stl/inc/iomanip index 851adaf457..24caf598ec 100644 --- a/stl/inc/iomanip +++ b/stl/inc/iomanip @@ -184,18 +184,6 @@ _NODISCARD _Timeobj<_Elem, const tm*> put_time(const tm* _Tptr_arg, const _Elem* return _Timeobj<_Elem, const tm*>(_Tptr_arg, _Fmt_arg); } -template -struct _Quote_in { // store reference to string - using _Mystr = basic_string<_Elem, _Traits, _Alloc>; - - _Quote_in(_Mystr& _Str_obj, _Elem _Delim_obj, _Elem _Escape_obj) - : _Str(_Str_obj), _Delim(_Delim_obj), _Escape(_Escape_obj) {} - - _Mystr& _Str; // reference to string - _Elem _Delim; // delimiter element - _Elem _Escape; // escape element -}; - template struct _Quote_out { // store pointer/length for string _Quote_out(const _Elem* _Ptr_obj, _Sizet _Size_obj, _Elem _Delim_obj, _Elem _Escape_obj) @@ -211,6 +199,18 @@ struct _Quote_out { // store pointer/length for string _Quote_out& operator=(const _Quote_out&) = delete; }; +template +struct _Quote_in { // store reference to string + using _Mystr = basic_string<_Elem, _Traits, _Alloc>; + + _Quote_in(_Mystr& _Str_obj, _Elem _Delim_obj, _Elem _Escape_obj) + : _Str(_Str_obj), _Delim(_Delim_obj), _Escape(_Escape_obj) {} + + _Mystr& _Str; // reference to string + _Elem _Delim; // delimiter element + _Elem _Escape; // escape element +}; + template _NODISCARD _Quote_out<_Elem, void, size_t> quoted( const _Elem* _Ptr, _Elem _Delim = _Elem('"'), _Elem _Escape = _Elem('\\')) { From 3c44ad5dcaacd8d9d60ea0639f1eca7233f37eea Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:41:53 -0700 Subject: [PATCH 09/11] Use friendship for _Quote_out. --- stl/inc/iomanip | 174 ++++++++++++++++++++++++------------------------ 1 file changed, 88 insertions(+), 86 deletions(-) diff --git a/stl/inc/iomanip b/stl/inc/iomanip index 24caf598ec..2c1302449e 100644 --- a/stl/inc/iomanip +++ b/stl/inc/iomanip @@ -191,6 +191,94 @@ struct _Quote_out { // store pointer/length for string _Quote_out(const _Quote_out&) = default; + template + friend basic_ostream<_Elem, _OsTraits>& operator<<( + basic_ostream<_Elem, _OsTraits>& _Ostr, const _Quote_out& _Manip) { + // put quoted string to output stream + static_assert( + is_void_v<_QuTraits> || is_same_v<_QuTraits, _OsTraits>, "quoted() traits must match basic_ostream traits"); + + using _Myos = basic_ostream<_Elem, _OsTraits>; + + const _Elem* const _Last = _Manip._Ptr + _Manip._Size; + + _Sizet _Size = _Manip._Size + 2; // allow for delimiters + for (const _Elem* _Ptr = _Manip._Ptr; _Ptr != _Last; ++_Ptr) { + if (_OsTraits::eq(*_Ptr, _Manip._Delim) || _OsTraits::eq(*_Ptr, _Manip._Escape)) { + ++_Size; // count escapes + } + } + + ios_base::iostate _State = ios_base::goodbit; + + _Sizet _Pad; + if (_Ostr.width() <= 0 || static_cast<_Sizet>(_Ostr.width()) <= _Size) { + _Pad = 0; + } else { + _Pad = static_cast<_Sizet>(_Ostr.width()) - _Size; + } + + const typename _Myos::sentry _Ok(_Ostr); + + if (!_Ok) { + _State |= ios_base::badbit; + } else { // state okay, insert characters + _TRY_IO_BEGIN + if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left) { + for (; 0 < _Pad; --_Pad) { // pad on left + if (_OsTraits::eq_int_type(_OsTraits::eof(), _Ostr.rdbuf()->sputc(_Ostr.fill()))) { + _State |= ios_base::badbit; // insertion failed, quit + break; + } + } + } + + if (_State == ios_base::goodbit + && _OsTraits::eq_int_type(_OsTraits::eof(), + _Ostr.rdbuf()->sputc(_Manip._Delim))) { // put delimiter + _State |= ios_base::badbit; + } + + for (const _Elem* _Ptr = _Manip._Ptr; _Ptr != _Last; ++_Ptr) { // put (possibly escaped) element + if ((_OsTraits::eq(*_Ptr, _Manip._Delim) || _OsTraits::eq(*_Ptr, _Manip._Escape)) + && _State == ios_base::goodbit + && _OsTraits::eq_int_type(_OsTraits::eof(), + _Ostr.rdbuf()->sputc(_Manip._Escape))) { // put escape + _State |= ios_base::badbit; // insertion failed, quit + break; + } + + if (_State == ios_base::goodbit + && _OsTraits::eq_int_type(_OsTraits::eof(), + _Ostr.rdbuf()->sputc(*_Ptr))) { // put element + _State |= ios_base::badbit; // insertion failed, quit + break; + } + } + + if (_State == ios_base::goodbit + && _OsTraits::eq_int_type(_OsTraits::eof(), + _Ostr.rdbuf()->sputc(_Manip._Delim))) { // put delimiter + _State |= ios_base::badbit; + } + + if (_State == ios_base::goodbit) { + for (; 0 < _Pad; --_Pad) { // pad on right + if (_OsTraits::eq_int_type(_OsTraits::eof(), _Ostr.rdbuf()->sputc(_Ostr.fill()))) { + _State |= ios_base::badbit; // insertion failed, quit + break; + } + } + } + + _Ostr.width(0); + _CATCH_IO_(ios_base, _Ostr) + } + + _Ostr.setstate(_State); + return _Ostr; + } + const _Elem* _Ptr; // pointer to string _Sizet _Size; // length of string _Elem _Delim; // delimiter element @@ -238,92 +326,6 @@ _NODISCARD _Quote_in<_Elem, _Traits, _Alloc> quoted( return {_Str, _Delim, _Escape}; } -template -basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, - const _Quote_out<_Elem, _QuTraits, _Sizet>& _Manip) { // put quoted string to output stream - static_assert( - is_void_v<_QuTraits> || is_same_v<_QuTraits, _Traits>, "quoted() traits must match basic_ostream traits"); - - using _Myos = basic_ostream<_Elem, _Traits>; - - const _Elem* const _Last = _Manip._Ptr + _Manip._Size; - - _Sizet _Size = _Manip._Size + 2; // allow for delimiters - for (const _Elem* _Ptr = _Manip._Ptr; _Ptr != _Last; ++_Ptr) { - if (_Traits::eq(*_Ptr, _Manip._Delim) || _Traits::eq(*_Ptr, _Manip._Escape)) { - ++_Size; // count escapes - } - } - - ios_base::iostate _State = ios_base::goodbit; - - _Sizet _Pad; - if (_Ostr.width() <= 0 || static_cast<_Sizet>(_Ostr.width()) <= _Size) { - _Pad = 0; - } else { - _Pad = static_cast<_Sizet>(_Ostr.width()) - _Size; - } - - const typename _Myos::sentry _Ok(_Ostr); - - if (!_Ok) { - _State |= ios_base::badbit; - } else { // state okay, insert characters - _TRY_IO_BEGIN - if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left) { - for (; 0 < _Pad; --_Pad) { // pad on left - if (_Traits::eq_int_type(_Traits::eof(), _Ostr.rdbuf()->sputc(_Ostr.fill()))) { - _State |= ios_base::badbit; // insertion failed, quit - break; - } - } - } - - if (_State == ios_base::goodbit - && _Traits::eq_int_type(_Traits::eof(), - _Ostr.rdbuf()->sputc(_Manip._Delim))) { // put delimiter - _State |= ios_base::badbit; - } - - for (const _Elem* _Ptr = _Manip._Ptr; _Ptr != _Last; ++_Ptr) { // put (possibly escaped) element - if ((_Traits::eq(*_Ptr, _Manip._Delim) || _Traits::eq(*_Ptr, _Manip._Escape)) && _State == ios_base::goodbit - && _Traits::eq_int_type(_Traits::eof(), - _Ostr.rdbuf()->sputc(_Manip._Escape))) { // put escape - _State |= ios_base::badbit; // insertion failed, quit - break; - } - - if (_State == ios_base::goodbit - && _Traits::eq_int_type(_Traits::eof(), - _Ostr.rdbuf()->sputc(*_Ptr))) { // put element - _State |= ios_base::badbit; // insertion failed, quit - break; - } - } - - if (_State == ios_base::goodbit - && _Traits::eq_int_type(_Traits::eof(), - _Ostr.rdbuf()->sputc(_Manip._Delim))) { // put delimiter - _State |= ios_base::badbit; - } - - if (_State == ios_base::goodbit) { - for (; 0 < _Pad; --_Pad) { // pad on right - if (_Traits::eq_int_type(_Traits::eof(), _Ostr.rdbuf()->sputc(_Ostr.fill()))) { - _State |= ios_base::badbit; // insertion failed, quit - break; - } - } - } - - _Ostr.width(0); - _CATCH_IO_(ios_base, _Ostr) - } - - _Ostr.setstate(_State); - return _Ostr; -} - template basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, const _Quote_in<_Elem, _Traits, _Alloc>& _Manip) { // put quoted string to output stream From dd59a07f75de658216a431ea6f804f1d01e9f886 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:55:19 -0700 Subject: [PATCH 10/11] Use friendship for _Quote_in, part 1. --- stl/inc/iomanip | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/stl/inc/iomanip b/stl/inc/iomanip index 2c1302449e..fcd9b4268c 100644 --- a/stl/inc/iomanip +++ b/stl/inc/iomanip @@ -294,6 +294,13 @@ struct _Quote_in { // store reference to string _Quote_in(_Mystr& _Str_obj, _Elem _Delim_obj, _Elem _Escape_obj) : _Str(_Str_obj), _Delim(_Delim_obj), _Escape(_Escape_obj) {} + friend basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, const _Quote_in& _Manip) { + // put quoted string to output stream + using _Out_type = _Quote_out<_Elem, _Traits, typename _Mystr::size_type>; + + return _Ostr << _Out_type{_Manip._Str.c_str(), _Manip._Str.size(), _Manip._Delim, _Manip._Escape}; + } + _Mystr& _Str; // reference to string _Elem _Delim; // delimiter element _Elem _Escape; // escape element @@ -326,15 +333,6 @@ _NODISCARD _Quote_in<_Elem, _Traits, _Alloc> quoted( return {_Str, _Delim, _Escape}; } -template -basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, - const _Quote_in<_Elem, _Traits, _Alloc>& _Manip) { // put quoted string to output stream - using _Mystr = basic_string<_Elem, _Traits, _Alloc>; - - const _Mystr& _Ref = _Manip._Str; - return _Ostr << _STD quoted(_Ref, _Manip._Delim, _Manip._Escape); -} - template basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, const _Quote_in<_Elem, _Traits, _Alloc>& _Manip) { // get quoted string from input stream From 326ee77c5d6cef9cd1d00be3ac0c2c839d31556f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Apr 2022 17:57:19 -0700 Subject: [PATCH 11/11] Use friendship for _Quote_in, part 2. --- stl/inc/iomanip | 93 ++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/stl/inc/iomanip b/stl/inc/iomanip index fcd9b4268c..711b792bd7 100644 --- a/stl/inc/iomanip +++ b/stl/inc/iomanip @@ -301,6 +301,52 @@ struct _Quote_in { // store reference to string return _Ostr << _Out_type{_Manip._Str.c_str(), _Manip._Str.size(), _Manip._Delim, _Manip._Escape}; } + friend basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, const _Quote_in& _Manip) { + // get quoted string from input stream + ios_base::iostate _State = ios_base::goodbit; + const typename basic_istream<_Elem, _Traits>::sentry _Ok(_Istr); + + if (_Ok) { // state okay, extract characters + _TRY_IO_BEGIN + const auto _Buf = _Istr.rdbuf(); + auto& _Str = _Manip._Str; + const auto _Delim = _Traits::to_int_type(_Manip._Delim); + auto _Meta = _Buf->sgetc(); + + if (!_Traits::eq_int_type(_Meta, _Delim)) { // no leading delimiter + return _Istr >> _Str; + } + + const auto _Escape = _Traits::to_int_type(_Manip._Escape); + _Str.clear(); + for (;;) { + _Meta = _Buf->snextc(); + if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // no trailing delimiter; fail + _State = ios_base::eofbit | ios_base::failbit; + break; + } else if (_Traits::eq_int_type(_Meta, _Escape)) { // escape; read next character literally + _Meta = _Buf->snextc(); + if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // bad escape; fail + _State = ios_base::eofbit | ios_base::failbit; + break; + } + } else if (_Traits::eq_int_type(_Meta, _Delim)) { // found trailing delimiter + if (_Traits::eq_int_type(_Traits::eof(), _Buf->sbumpc())) { // consume trailing delimiter + _State = ios_base::eofbit; + } + + break; + } + + _Str.push_back(_Traits::to_char_type(_Meta)); + } + _CATCH_IO_(ios_base, _Istr) + } + + _Istr.setstate(_State); + return _Istr; + } + _Mystr& _Str; // reference to string _Elem _Delim; // delimiter element _Elem _Escape; // escape element @@ -333,53 +379,6 @@ _NODISCARD _Quote_in<_Elem, _Traits, _Alloc> quoted( return {_Str, _Delim, _Escape}; } -template -basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, - const _Quote_in<_Elem, _Traits, _Alloc>& _Manip) { // get quoted string from input stream - ios_base::iostate _State = ios_base::goodbit; - const typename basic_istream<_Elem, _Traits>::sentry _Ok(_Istr); - - if (_Ok) { // state okay, extract characters - _TRY_IO_BEGIN - const auto _Buf = _Istr.rdbuf(); - auto& _Str = _Manip._Str; - const auto _Delim = _Traits::to_int_type(_Manip._Delim); - auto _Meta = _Buf->sgetc(); - - if (!_Traits::eq_int_type(_Meta, _Delim)) { // no leading delimiter - return _Istr >> _Str; - } - - const auto _Escape = _Traits::to_int_type(_Manip._Escape); - _Str.clear(); - for (;;) { - _Meta = _Buf->snextc(); - if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // no trailing delimiter; fail - _State = ios_base::eofbit | ios_base::failbit; - break; - } else if (_Traits::eq_int_type(_Meta, _Escape)) { // escape; read next character literally - _Meta = _Buf->snextc(); - if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // bad escape; fail - _State = ios_base::eofbit | ios_base::failbit; - break; - } - } else if (_Traits::eq_int_type(_Meta, _Delim)) { // found trailing delimiter - if (_Traits::eq_int_type(_Traits::eof(), _Buf->sbumpc())) { // consume trailing delimiter - _State = ios_base::eofbit; - } - - break; - } - - _Str.push_back(_Traits::to_char_type(_Meta)); - } - _CATCH_IO_(ios_base, _Istr) - } - - _Istr.setstate(_State); - return _Istr; -} - template struct _Smanip { // store function pointer and argument value _Smanip(void(__cdecl* _Left)(ios_base&, _Arg), _Arg _Val) : _Pfun(_Left), _Manarg(_Val) {}