зеркало из https://github.com/microsoft/STL.git
Implement `formatter<vector<bool>::reference>` (#4133)
Co-authored-by: Casey Carter <cacarter@microsoft.com> Co-authored-by: Stephan T. Lavavej <stl@microsoft.com> Co-authored-by: Jakub Mazurkiewicz <mazkuba3@gmail.com>
This commit is contained in:
Родитель
730af178f7
Коммит
8234695bd7
|
@ -12,6 +12,7 @@ set(HEADERS
|
|||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_cxx_stdatomic.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_filebuf.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_format_ucd_tables.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_formatter.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_int128.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_iter_core.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_print.hpp
|
||||
|
|
|
@ -0,0 +1,277 @@
|
|||
// __msvc_formatter.hpp internal header
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// NOTE:
|
||||
// The contents of this header are derived in part from libfmt under the following license:
|
||||
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// --- Optional exception to the license ---
|
||||
//
|
||||
// As an exception, if, as a result of your compiling your source code, portions
|
||||
// of this Software are embedded into a machine-executable object form of such
|
||||
// source code, you may redistribute such embedded portions in such object form
|
||||
// without including the above copyright and permission notices.
|
||||
|
||||
#ifndef __MSVC_FORMATTER_HPP
|
||||
#define __MSVC_FORMATTER_HPP
|
||||
#include <yvals_core.h>
|
||||
#if _STL_COMPILER_PREPROCESSOR
|
||||
|
||||
#if !_HAS_CXX20 || !defined(__cpp_lib_concepts) // TRANSITION, GH-395
|
||||
#error The contents of <format> are only available with C++20. (Also, you should not include this internal header.)
|
||||
#endif // !_HAS_CXX20 || !defined(__cpp_lib_concepts)
|
||||
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#pragma pack(push, _CRT_PACKING)
|
||||
#pragma warning(push, _STL_WARNING_LEVEL)
|
||||
#pragma warning(disable : _STL_DISABLED_WARNINGS)
|
||||
_STL_DISABLE_CLANG_WARNINGS
|
||||
#pragma push_macro("new")
|
||||
#undef new
|
||||
|
||||
_STD_BEGIN
|
||||
#if _HAS_CXX23
|
||||
#define _FMT_P2286_BEGIN inline namespace __p2286 {
|
||||
#define _FMT_P2286_END }
|
||||
#else // ^^^ _HAS_CXX23 / !_HAS_CXX23 vvv
|
||||
#define _FMT_P2286_BEGIN
|
||||
#define _FMT_P2286_END
|
||||
#endif // ^^^ !_HAS_CXX23 ^^^
|
||||
|
||||
enum class _Fmt_align : uint8_t { _None, _Left, _Right, _Center };
|
||||
|
||||
enum class _Fmt_sign : uint8_t { _None, _Plus, _Minus, _Space };
|
||||
|
||||
enum class _Basic_format_arg_type : uint8_t {
|
||||
_None,
|
||||
_Int_type,
|
||||
_UInt_type,
|
||||
_Long_long_type,
|
||||
_ULong_long_type,
|
||||
_Bool_type,
|
||||
_Char_type,
|
||||
_Float_type,
|
||||
_Double_type,
|
||||
_Long_double_type,
|
||||
_Pointer_type,
|
||||
_CString_type,
|
||||
_String_type,
|
||||
_Custom_type,
|
||||
};
|
||||
static_assert(static_cast<int>(_Basic_format_arg_type::_Custom_type) < 16, "must fit in 4-bit bitfield");
|
||||
|
||||
#if _HAS_CXX23
|
||||
_NODISCARD consteval bool _Is_debug_enabled_fmt_type(_Basic_format_arg_type _Ty) {
|
||||
return _Ty == _Basic_format_arg_type::_Char_type || _Ty == _Basic_format_arg_type::_CString_type
|
||||
|| _Ty == _Basic_format_arg_type::_String_type;
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
template <class _CharT>
|
||||
struct _Basic_format_specs {
|
||||
int _Width = 0;
|
||||
int _Precision = -1;
|
||||
char _Type = '\0';
|
||||
_Fmt_align _Alignment = _Fmt_align::_None;
|
||||
_Fmt_sign _Sgn = _Fmt_sign::_None;
|
||||
bool _Alt = false;
|
||||
bool _Localized = false;
|
||||
bool _Leading_zero = false;
|
||||
uint8_t _Fill_length = 1;
|
||||
// At most one codepoint (so one char32_t or four utf-8 char8_t).
|
||||
_CharT _Fill[4 / sizeof(_CharT)] = {_CharT{' '}};
|
||||
};
|
||||
|
||||
// Adds width and precision references to _Basic_format_specs.
|
||||
// This is required for std::formatter implementations because we must
|
||||
// parse the format specs without having access to the format args (via a format context).
|
||||
template <class _CharT>
|
||||
struct _Dynamic_format_specs : _Basic_format_specs<_CharT> {
|
||||
int _Dynamic_width_index = -1;
|
||||
int _Dynamic_precision_index = -1;
|
||||
};
|
||||
|
||||
_EXPORT_STD template <class _CharT>
|
||||
class basic_format_parse_context;
|
||||
|
||||
template <class _CharT>
|
||||
concept _Format_supported_charT = _Is_any_of_v<_CharT, char, wchar_t>;
|
||||
|
||||
// Generic formatter definition, the deleted default constructor
|
||||
// makes it "disabled" as per N4950 [format.formatter.spec]/5
|
||||
_EXPORT_STD template <class _Ty, class _CharT = char>
|
||||
struct formatter {
|
||||
formatter() = delete;
|
||||
formatter(const formatter&) = delete;
|
||||
formatter operator=(const formatter&) = delete;
|
||||
};
|
||||
|
||||
_FMT_P2286_BEGIN
|
||||
// TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers.
|
||||
template <_Basic_format_arg_type _ArgType, class _CharT, class _Pc>
|
||||
constexpr _Pc::iterator _Formatter_base_parse(_Dynamic_format_specs<_CharT>& _Specs, _Pc& _ParseCtx);
|
||||
|
||||
template <class _Ty, class _CharT, class _FormatContext>
|
||||
_FormatContext::iterator _Formatter_base_format(
|
||||
const _Dynamic_format_specs<_CharT>& _Specs, const _Ty& _Val, _FormatContext& _FormatCtx);
|
||||
|
||||
template <class _Ty, class _CharT, _Basic_format_arg_type _ArgType>
|
||||
struct _Formatter_base {
|
||||
public:
|
||||
#if _HAS_CXX23
|
||||
constexpr void _Set_debug_format() noexcept
|
||||
requires (_Is_debug_enabled_fmt_type(_ArgType))
|
||||
{
|
||||
_Specs._Type = '?';
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
template <class _Pc = basic_format_parse_context<_CharT>>
|
||||
constexpr _Pc::iterator parse(type_identity_t<_Pc&> _ParseCtx) {
|
||||
return _Formatter_base_parse<_ArgType>(_Specs, _ParseCtx);
|
||||
}
|
||||
|
||||
template <class _FormatContext>
|
||||
_FormatContext::iterator format(const _Ty& _Val, _FormatContext& _FormatCtx) const {
|
||||
return _Formatter_base_format(_Specs, _Val, _FormatCtx);
|
||||
}
|
||||
|
||||
private:
|
||||
_Dynamic_format_specs<_CharT> _Specs;
|
||||
};
|
||||
_FMT_P2286_END
|
||||
|
||||
#define _FORMAT_SPECIALIZE_FOR(_Type, _ArgType) \
|
||||
template <_Format_supported_charT _CharT> \
|
||||
struct formatter<_Type, _CharT> : _Formatter_base<_Type, _CharT, _ArgType> {}
|
||||
|
||||
_FORMAT_SPECIALIZE_FOR(int, _Basic_format_arg_type::_Int_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned int, _Basic_format_arg_type::_UInt_type);
|
||||
_FORMAT_SPECIALIZE_FOR(long long, _Basic_format_arg_type::_Long_long_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned long long, _Basic_format_arg_type::_ULong_long_type);
|
||||
_FORMAT_SPECIALIZE_FOR(bool, _Basic_format_arg_type::_Bool_type);
|
||||
_FORMAT_SPECIALIZE_FOR(float, _Basic_format_arg_type::_Float_type);
|
||||
_FORMAT_SPECIALIZE_FOR(double, _Basic_format_arg_type::_Double_type);
|
||||
_FORMAT_SPECIALIZE_FOR(long double, _Basic_format_arg_type::_Long_double_type);
|
||||
_FORMAT_SPECIALIZE_FOR(nullptr_t, _Basic_format_arg_type::_Pointer_type);
|
||||
_FORMAT_SPECIALIZE_FOR(void*, _Basic_format_arg_type::_Pointer_type);
|
||||
_FORMAT_SPECIALIZE_FOR(const void*, _Basic_format_arg_type::_Pointer_type);
|
||||
_FORMAT_SPECIALIZE_FOR(short, _Basic_format_arg_type::_Int_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned short, _Basic_format_arg_type::_UInt_type);
|
||||
_FORMAT_SPECIALIZE_FOR(long, _Basic_format_arg_type::_Int_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned long, _Basic_format_arg_type::_UInt_type);
|
||||
_FORMAT_SPECIALIZE_FOR(signed char, _Basic_format_arg_type::_Int_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned char, _Basic_format_arg_type::_UInt_type);
|
||||
|
||||
#undef _FORMAT_SPECIALIZE_FOR
|
||||
|
||||
// not using the macro because we'd like to add 'set_debug_format' member function in C++23 mode
|
||||
template <_Format_supported_charT _CharT>
|
||||
struct formatter<char, _CharT> : _Formatter_base<char, _CharT, _Basic_format_arg_type::_Char_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
// not using the macro because we'd like to avoid the formatter<wchar_t, char> specialization
|
||||
template <>
|
||||
struct formatter<wchar_t, wchar_t> : _Formatter_base<wchar_t, wchar_t, _Basic_format_arg_type::_Char_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
// We could use the macro for these specializations, but it's confusing to refer to symbols that are defined
|
||||
// inside the macro in the macro's "call".
|
||||
template <_Format_supported_charT _CharT>
|
||||
struct formatter<_CharT*, _CharT> : _Formatter_base<_CharT*, _CharT, _Basic_format_arg_type::_CString_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
template <_Format_supported_charT _CharT>
|
||||
struct formatter<const _CharT*, _CharT>
|
||||
: _Formatter_base<const _CharT*, _CharT, _Basic_format_arg_type::_CString_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
template <_Format_supported_charT _CharT, size_t _Nx>
|
||||
struct formatter<_CharT[_Nx], _CharT> : _Formatter_base<_CharT[_Nx], _CharT, _Basic_format_arg_type::_CString_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
_EXPORT_STD template <class _Elem, class _Traits, class _Alloc>
|
||||
class basic_string;
|
||||
|
||||
_EXPORT_STD template <class _Elem, class _Traits>
|
||||
class basic_string_view;
|
||||
|
||||
template <_Format_supported_charT _CharT, class _Traits, class _Allocator>
|
||||
struct formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT>
|
||||
: _Formatter_base<basic_string<_CharT, _Traits, _Allocator>, _CharT, _Basic_format_arg_type::_String_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
template <_Format_supported_charT _CharT, class _Traits>
|
||||
struct formatter<basic_string_view<_CharT, _Traits>, _CharT>
|
||||
: _Formatter_base<basic_string_view<_CharT, _Traits>, _CharT, _Basic_format_arg_type::_String_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
_STD_END
|
||||
|
||||
#pragma pop_macro("new")
|
||||
_STL_RESTORE_CLANG_WARNINGS
|
||||
#pragma warning(pop)
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // _STL_COMPILER_PREPROCESSOR
|
||||
#endif // __MSVC_FORMATTER_HPP
|
|
@ -5812,7 +5812,8 @@ private:
|
|||
_CHRONO _Chrono_formatter<_CharT> _Impl;
|
||||
};
|
||||
|
||||
// Per LWG-3997, the _CharT template parameter is constrained to supported character types.
|
||||
// Per LWG-3997, `_CharT` in library-provided `formatter` specializations is
|
||||
// constrained to character types supported by `format`.
|
||||
|
||||
template <class _Rep, class _Period, _Format_supported_charT _CharT>
|
||||
struct formatter<_CHRONO duration<_Rep, _Period>, _CharT>
|
||||
|
|
273
stl/inc/format
273
stl/inc/format
|
@ -43,6 +43,7 @@ _EMIT_STL_WARNING(STL4038, "The contents of <format> are available only with C++
|
|||
#else // ^^^ !defined(__cpp_lib_concepts) / defined(__cpp_lib_concepts) vvv
|
||||
|
||||
#include <__msvc_format_ucd_tables.hpp>
|
||||
#include <__msvc_formatter.hpp>
|
||||
#include <__msvc_print.hpp>
|
||||
#include <bit>
|
||||
#include <charconv>
|
||||
|
@ -67,15 +68,6 @@ _STL_DISABLE_CLANG_WARNINGS
|
|||
extern "C" _NODISCARD __std_win_error __stdcall __std_get_cvt(__std_code_page _Codepage, _Cvtvec* _Pcvt) noexcept;
|
||||
|
||||
_STD_BEGIN
|
||||
|
||||
#if _HAS_CXX23
|
||||
#define _FMT_P2286_BEGIN inline namespace __p2286 {
|
||||
#define _FMT_P2286_END }
|
||||
#else // ^^^ C++23 / C++20 vvv
|
||||
#define _FMT_P2286_BEGIN
|
||||
#define _FMT_P2286_END
|
||||
#endif // ^^^ C++20 ^^^
|
||||
|
||||
template <class _CharT>
|
||||
_NODISCARD constexpr const _CharT* _Choose_literal(const char* const _Str, const wchar_t* const _WStr) noexcept {
|
||||
if constexpr (is_same_v<_CharT, char>) {
|
||||
|
@ -100,28 +92,6 @@ _EXPORT_STD class format_error : public runtime_error {
|
|||
_THROW(format_error{_Message});
|
||||
}
|
||||
|
||||
enum class _Fmt_align : uint8_t { _None, _Left, _Right, _Center };
|
||||
|
||||
enum class _Fmt_sign : uint8_t { _None, _Plus, _Minus, _Space };
|
||||
|
||||
enum class _Basic_format_arg_type : uint8_t {
|
||||
_None,
|
||||
_Int_type,
|
||||
_UInt_type,
|
||||
_Long_long_type,
|
||||
_ULong_long_type,
|
||||
_Bool_type,
|
||||
_Char_type,
|
||||
_Float_type,
|
||||
_Double_type,
|
||||
_Long_double_type,
|
||||
_Pointer_type,
|
||||
_CString_type,
|
||||
_String_type,
|
||||
_Custom_type,
|
||||
};
|
||||
static_assert(static_cast<int>(_Basic_format_arg_type::_Custom_type) < 16, "must fit in 4-bit bitfield");
|
||||
|
||||
_NODISCARD constexpr bool _Is_integral_fmt_type(_Basic_format_arg_type _Ty) {
|
||||
return _Ty > _Basic_format_arg_type::_None && _Ty <= _Basic_format_arg_type::_Char_type;
|
||||
}
|
||||
|
@ -130,13 +100,6 @@ _NODISCARD constexpr bool _Is_arithmetic_fmt_type(_Basic_format_arg_type _Ty) {
|
|||
return _Ty > _Basic_format_arg_type::_None && _Ty <= _Basic_format_arg_type::_Long_double_type;
|
||||
}
|
||||
|
||||
#if _HAS_CXX23
|
||||
_NODISCARD consteval bool _Is_debug_enabled_fmt_type(_Basic_format_arg_type _Ty) {
|
||||
return _Ty == _Basic_format_arg_type::_Char_type || _Ty == _Basic_format_arg_type::_CString_type
|
||||
|| _Ty == _Basic_format_arg_type::_String_type;
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
struct _Auto_id_tag {
|
||||
explicit _Auto_id_tag() = default;
|
||||
};
|
||||
|
@ -571,12 +534,6 @@ public:
|
|||
template <class _Ty, class _CharT>
|
||||
concept _CharT_or_bool = same_as<_Ty, _CharT> || same_as<_Ty, bool>;
|
||||
|
||||
template <class _CharT>
|
||||
concept _Format_supported_charT = _Is_any_of_v<_CharT, char, wchar_t>;
|
||||
|
||||
_EXPORT_STD template <class _Ty, class _CharT = char>
|
||||
struct formatter;
|
||||
|
||||
inline void _You_see_this_error_because_arg_id_is_out_of_range() noexcept {}
|
||||
inline void _Invalid_arg_type_for_dynamic_width_or_precision() noexcept {}
|
||||
|
||||
|
@ -710,7 +667,7 @@ struct _Format_arg_traits {
|
|||
|
||||
// Function template _Type_eraser mirrors the type dispatching mechanism in the construction of basic_format_arg
|
||||
// (N4950 [format.arg]). They determine the mapping from "raw" to "erased" argument type for _Format_arg_store.
|
||||
template <_Formattable_with<_Context> _Ty>
|
||||
template <class _Ty>
|
||||
static auto _Type_eraser();
|
||||
|
||||
template <class _Ty>
|
||||
|
@ -877,7 +834,7 @@ private:
|
|||
};
|
||||
|
||||
template <class _Context>
|
||||
template <_Formattable_with<_Context> _Ty>
|
||||
template <class _Ty>
|
||||
auto _Format_arg_traits<_Context>::_Type_eraser() {
|
||||
using _Td = remove_const_t<_Ty>;
|
||||
// See N4950 [format.arg]/6
|
||||
|
@ -1593,30 +1550,6 @@ constexpr void _Parse_format_string(basic_string_view<_CharT> _Format_str, _Hand
|
|||
}
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
struct _Basic_format_specs {
|
||||
int _Width = 0;
|
||||
int _Precision = -1;
|
||||
char _Type = '\0';
|
||||
_Fmt_align _Alignment = _Fmt_align::_None;
|
||||
_Fmt_sign _Sgn = _Fmt_sign::_None;
|
||||
bool _Alt = false;
|
||||
bool _Localized = false;
|
||||
bool _Leading_zero = false;
|
||||
uint8_t _Fill_length = 1;
|
||||
// At most one codepoint (so one char32_t or four utf-8 char8_t).
|
||||
_CharT _Fill[4 / sizeof(_CharT)] = {_CharT{' '}};
|
||||
};
|
||||
|
||||
// Adds width and precision references to _Basic_format_specs.
|
||||
// This is required for std::formatter implementations because we must
|
||||
// parse the format specs without having access to the format args (via a format context).
|
||||
template <class _CharT>
|
||||
struct _Dynamic_format_specs : _Basic_format_specs<_CharT> {
|
||||
int _Dynamic_width_index = -1;
|
||||
int _Dynamic_precision_index = -1;
|
||||
};
|
||||
|
||||
// Model of _Parse_spec_callbacks that fills a _Basic_format_specs with the parsed data.
|
||||
template <class _CharT>
|
||||
class _Specs_setter {
|
||||
|
@ -2281,14 +2214,9 @@ public:
|
|||
#if _HAS_CXX23
|
||||
template <class _CharT>
|
||||
struct _Phony_fmt_iter_for {
|
||||
using iterator_category = output_iterator_tag;
|
||||
using value_type = _CharT;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = _CharT*;
|
||||
using reference = _CharT&;
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
reference operator*() const;
|
||||
pointer operator->() const;
|
||||
_CharT& operator*() const;
|
||||
|
||||
_Phony_fmt_iter_for& operator++();
|
||||
_Phony_fmt_iter_for operator++(int);
|
||||
|
@ -2508,7 +2436,7 @@ struct _Invalid_format_kind {
|
|||
};
|
||||
|
||||
_EXPORT_STD template <class _Ty>
|
||||
constexpr _Invalid_format_kind<_Ty> format_kind{};
|
||||
inline constexpr _Invalid_format_kind<_Ty> format_kind;
|
||||
|
||||
template <class _Ty>
|
||||
inline constexpr bool _Is_two_tuple = false;
|
||||
|
@ -2521,7 +2449,7 @@ inline constexpr bool _Is_two_tuple<tuple<_Ty, _Uty>> = true;
|
|||
|
||||
template <_RANGES input_range _Rng>
|
||||
requires same_as<_Rng, remove_cvref_t<_Rng>>
|
||||
constexpr range_format format_kind<_Rng> = []() consteval {
|
||||
inline constexpr range_format format_kind<_Rng> = []() consteval {
|
||||
using _Ref_value_t = remove_cvref_t<_RANGES range_reference_t<_Rng>>;
|
||||
if constexpr (same_as<_Ref_value_t, _Rng>) {
|
||||
return range_format::disabled;
|
||||
|
@ -3692,159 +3620,38 @@ struct _Format_handler {
|
|||
return _First;
|
||||
}
|
||||
};
|
||||
|
||||
template <_Basic_format_arg_type _ArgType, class _CharT, class _Pc>
|
||||
constexpr _Pc::iterator _Formatter_base_parse(_Dynamic_format_specs<_CharT>& _Specs, _Pc& _ParseCtx) {
|
||||
_Specs_checker<_Dynamic_specs_handler<_Pc>> _Handler(_Dynamic_specs_handler<_Pc>{_Specs, _ParseCtx}, _ArgType);
|
||||
const auto _It = _Parse_format_specs(_ParseCtx._Unchecked_begin(), _ParseCtx._Unchecked_end(), _Handler);
|
||||
if (_It != _ParseCtx._Unchecked_end() && *_It != '}') {
|
||||
_Throw_format_error("Missing '}' in format string.");
|
||||
}
|
||||
return _ParseCtx.begin() + (_It - _ParseCtx._Unchecked_begin());
|
||||
}
|
||||
|
||||
template <class _Ty, class _CharT, class _FormatContext>
|
||||
_FormatContext::iterator _Formatter_base_format(
|
||||
const _Dynamic_format_specs<_CharT>& _Specs, const _Ty& _Val, _FormatContext& _FormatCtx) {
|
||||
_Dynamic_format_specs<_CharT> _Format_specs = _Specs;
|
||||
if (_Specs._Dynamic_width_index >= 0) {
|
||||
_Format_specs._Width =
|
||||
_Get_dynamic_specs<_Width_checker>(_FormatCtx.arg(static_cast<size_t>(_Specs._Dynamic_width_index)));
|
||||
}
|
||||
|
||||
if (_Specs._Dynamic_precision_index >= 0) {
|
||||
_Format_specs._Precision = _Get_dynamic_specs<_Precision_checker>(
|
||||
_FormatCtx.arg(static_cast<size_t>(_Specs._Dynamic_precision_index)));
|
||||
}
|
||||
|
||||
return _STD visit_format_arg(
|
||||
_Arg_formatter<typename _FormatContext::iterator, _CharT>{
|
||||
._Ctx = _STD addressof(_FormatCtx), ._Specs = _STD addressof(_Format_specs)},
|
||||
basic_format_arg<_FormatContext>::_Make_from(_Val));
|
||||
}
|
||||
_FMT_P2286_END
|
||||
|
||||
// Generic formatter definition, the deleted default constructor
|
||||
// makes it "disabled" as per N4950 [format.formatter.spec]/5
|
||||
_EXPORT_STD template <class _Ty, class _CharT>
|
||||
struct formatter {
|
||||
formatter() = delete;
|
||||
formatter(const formatter&) = delete;
|
||||
formatter operator=(const formatter&) = delete;
|
||||
};
|
||||
|
||||
_FMT_P2286_BEGIN
|
||||
template <class _Ty, class _CharT, _Basic_format_arg_type _ArgType>
|
||||
struct _Formatter_base {
|
||||
private:
|
||||
using _Pc = basic_format_parse_context<_CharT>;
|
||||
|
||||
public:
|
||||
#if _HAS_CXX23
|
||||
constexpr void _Set_debug_format() noexcept
|
||||
requires (_Is_debug_enabled_fmt_type(_ArgType))
|
||||
{
|
||||
_Specs._Type = '?';
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
constexpr _Pc::iterator parse(_Pc& _ParseCtx) {
|
||||
_Specs_checker<_Dynamic_specs_handler<_Pc>> _Handler(_Dynamic_specs_handler<_Pc>{_Specs, _ParseCtx}, _ArgType);
|
||||
const auto _It = _Parse_format_specs(_ParseCtx._Unchecked_begin(), _ParseCtx._Unchecked_end(), _Handler);
|
||||
if (_It != _ParseCtx._Unchecked_end() && *_It != '}') {
|
||||
_Throw_format_error("Missing '}' in format string.");
|
||||
}
|
||||
return _ParseCtx.begin() + (_It - _ParseCtx._Unchecked_begin());
|
||||
}
|
||||
|
||||
template <class _FormatContext>
|
||||
_FormatContext::iterator format(const _Ty& _Val, _FormatContext& _FormatCtx) const {
|
||||
_Dynamic_format_specs<_CharT> _Format_specs = _Specs;
|
||||
if (_Specs._Dynamic_width_index >= 0) {
|
||||
_Format_specs._Width =
|
||||
_Get_dynamic_specs<_Width_checker>(_FormatCtx.arg(static_cast<size_t>(_Specs._Dynamic_width_index)));
|
||||
}
|
||||
|
||||
if (_Specs._Dynamic_precision_index >= 0) {
|
||||
_Format_specs._Precision = _Get_dynamic_specs<_Precision_checker>(
|
||||
_FormatCtx.arg(static_cast<size_t>(_Specs._Dynamic_precision_index)));
|
||||
}
|
||||
|
||||
return _STD visit_format_arg(
|
||||
_Arg_formatter<typename _FormatContext::iterator, _CharT>{
|
||||
._Ctx = _STD addressof(_FormatCtx), ._Specs = _STD addressof(_Format_specs)},
|
||||
basic_format_arg<_FormatContext>::_Make_from(_Val));
|
||||
}
|
||||
|
||||
private:
|
||||
_Dynamic_format_specs<_CharT> _Specs;
|
||||
};
|
||||
_FMT_P2286_END
|
||||
|
||||
#define _FORMAT_SPECIALIZE_FOR(_Type, _ArgType) \
|
||||
template <_Format_supported_charT _CharT> \
|
||||
struct formatter<_Type, _CharT> : _Formatter_base<_Type, _CharT, _ArgType> {}
|
||||
|
||||
_FORMAT_SPECIALIZE_FOR(int, _Basic_format_arg_type::_Int_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned int, _Basic_format_arg_type::_UInt_type);
|
||||
_FORMAT_SPECIALIZE_FOR(long long, _Basic_format_arg_type::_Long_long_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned long long, _Basic_format_arg_type::_ULong_long_type);
|
||||
_FORMAT_SPECIALIZE_FOR(bool, _Basic_format_arg_type::_Bool_type);
|
||||
_FORMAT_SPECIALIZE_FOR(float, _Basic_format_arg_type::_Float_type);
|
||||
_FORMAT_SPECIALIZE_FOR(double, _Basic_format_arg_type::_Double_type);
|
||||
_FORMAT_SPECIALIZE_FOR(long double, _Basic_format_arg_type::_Long_double_type);
|
||||
_FORMAT_SPECIALIZE_FOR(nullptr_t, _Basic_format_arg_type::_Pointer_type);
|
||||
_FORMAT_SPECIALIZE_FOR(void*, _Basic_format_arg_type::_Pointer_type);
|
||||
_FORMAT_SPECIALIZE_FOR(const void*, _Basic_format_arg_type::_Pointer_type);
|
||||
_FORMAT_SPECIALIZE_FOR(short, _Basic_format_arg_type::_Int_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned short, _Basic_format_arg_type::_UInt_type);
|
||||
_FORMAT_SPECIALIZE_FOR(long, _Basic_format_arg_type::_Int_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned long, _Basic_format_arg_type::_UInt_type);
|
||||
_FORMAT_SPECIALIZE_FOR(signed char, _Basic_format_arg_type::_Int_type);
|
||||
_FORMAT_SPECIALIZE_FOR(unsigned char, _Basic_format_arg_type::_UInt_type);
|
||||
|
||||
#undef _FORMAT_SPECIALIZE_FOR
|
||||
|
||||
// not using the macro because we'd like to add 'set_debug_format' member function in C++23 mode
|
||||
template <_Format_supported_charT _CharT>
|
||||
struct formatter<char, _CharT> : _Formatter_base<char, _CharT, _Basic_format_arg_type::_Char_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
// not using the macro because we'd like to avoid the formatter<wchar_t, char> specialization
|
||||
template <>
|
||||
struct formatter<wchar_t, wchar_t> : _Formatter_base<wchar_t, wchar_t, _Basic_format_arg_type::_Char_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
// We could use the macro for these specializations, but it's confusing to refer to symbols that are defined
|
||||
// inside the macro in the macro's "call".
|
||||
template <_Format_supported_charT _CharT>
|
||||
struct formatter<_CharT*, _CharT> : _Formatter_base<_CharT*, _CharT, _Basic_format_arg_type::_CString_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
template <_Format_supported_charT _CharT>
|
||||
struct formatter<const _CharT*, _CharT>
|
||||
: _Formatter_base<const _CharT*, _CharT, _Basic_format_arg_type::_CString_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
template <_Format_supported_charT _CharT, size_t _Nx>
|
||||
struct formatter<_CharT[_Nx], _CharT> : _Formatter_base<_CharT[_Nx], _CharT, _Basic_format_arg_type::_CString_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
template <_Format_supported_charT _CharT, class _Traits, class _Allocator>
|
||||
struct formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT>
|
||||
: _Formatter_base<basic_string<_CharT, _Traits, _Allocator>, _CharT, _Basic_format_arg_type::_String_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
template <_Format_supported_charT _CharT, class _Traits>
|
||||
struct formatter<basic_string_view<_CharT, _Traits>, _CharT>
|
||||
: _Formatter_base<basic_string_view<_CharT, _Traits>, _CharT, _Basic_format_arg_type::_String_type> {
|
||||
#if _HAS_CXX23
|
||||
constexpr void set_debug_format() noexcept {
|
||||
this->_Set_debug_format();
|
||||
}
|
||||
#endif // _HAS_CXX23
|
||||
};
|
||||
|
||||
_EXPORT_STD template <class _CharT, class... _Args>
|
||||
struct basic_format_string {
|
||||
public:
|
||||
|
@ -4225,7 +4032,7 @@ _NODISCARD constexpr const _CharT* _Parse_fill_align_and_width_specs(
|
|||
template <class _CharT>
|
||||
struct _Fill_align_and_width_formatter {
|
||||
public:
|
||||
_NODISCARD constexpr auto parse(basic_format_parse_context<_CharT>& _Parse_ctx) {
|
||||
_NODISCARD constexpr auto _Parse(basic_format_parse_context<_CharT>& _Parse_ctx) {
|
||||
_Fill_align_and_width_specs_setter<_CharT> _Callback{_Specs, _Parse_ctx};
|
||||
const auto _It =
|
||||
_Parse_fill_align_and_width_specs(_Parse_ctx._Unchecked_begin(), _Parse_ctx._Unchecked_end(), _Callback);
|
||||
|
@ -4252,10 +4059,6 @@ private:
|
|||
_Fill_align_and_width_specs<_CharT> _Specs;
|
||||
};
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
#undef _FMT_P2286_END
|
||||
#undef _FMT_P2286_BEGIN
|
||||
|
||||
_STD_END
|
||||
|
||||
#pragma pop_macro("new")
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"__msvc_cxx_stdatomic.hpp",
|
||||
"__msvc_filebuf.hpp",
|
||||
"__msvc_format_ucd_tables.hpp",
|
||||
"__msvc_formatter.hpp",
|
||||
"__msvc_int128.hpp",
|
||||
"__msvc_iter_core.hpp",
|
||||
"__msvc_print.hpp",
|
||||
|
|
|
@ -13,11 +13,14 @@ _EMIT_STL_WARNING(STL4038, "The contents of <stacktrace> are available only with
|
|||
#else // ^^^ !_HAS_CXX23 / _HAS_CXX23 vvv
|
||||
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __cpp_lib_concepts
|
||||
#include <format>
|
||||
#endif // __cpp_lib_concepts
|
||||
|
||||
#pragma pack(push, _CRT_PACKING)
|
||||
#pragma warning(push, _STL_WARNING_LEVEL)
|
||||
#pragma warning(disable : _STL_DISABLED_WARNINGS)
|
||||
|
@ -353,7 +356,7 @@ ostream& operator<<(ostream& _Os, const basic_stacktrace<_Alloc>& _St) {
|
|||
template <>
|
||||
struct formatter<stacktrace_entry> {
|
||||
constexpr format_parse_context::iterator parse(format_parse_context& _Parse_ctx) {
|
||||
return _Impl.parse(_Parse_ctx);
|
||||
return _Impl._Parse(_Parse_ctx);
|
||||
}
|
||||
|
||||
template <class _FormatContext>
|
||||
|
|
|
@ -437,38 +437,6 @@ _EXPORT_STD _NODISCARD inline long double stold(const wstring& _Str, size_t* _Id
|
|||
return _Ans;
|
||||
}
|
||||
|
||||
template <class _Elem, class _UTy>
|
||||
_NODISCARD _Elem* _UIntegral_to_buff(_Elem* _RNext, _UTy _UVal) {
|
||||
// format _UVal into buffer *ending at* _RNext
|
||||
static_assert(is_unsigned_v<_UTy>, "_UTy must be unsigned");
|
||||
|
||||
#ifdef _WIN64
|
||||
auto _UVal_trunc = _UVal;
|
||||
#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv
|
||||
|
||||
constexpr bool _Big_uty = sizeof(_UTy) > 4;
|
||||
if constexpr (_Big_uty) { // For 64-bit numbers, work in chunks to avoid 64-bit divisions.
|
||||
while (_UVal > 0xFFFFFFFFU) {
|
||||
auto _UVal_chunk = static_cast<unsigned long>(_UVal % 1000000000);
|
||||
_UVal /= 1000000000;
|
||||
|
||||
for (int _Idx = 0; _Idx != 9; ++_Idx) {
|
||||
*--_RNext = static_cast<_Elem>('0' + _UVal_chunk % 10);
|
||||
_UVal_chunk /= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto _UVal_trunc = static_cast<unsigned long>(_UVal);
|
||||
#endif // ^^^ !defined(_WIN64) ^^^
|
||||
|
||||
do {
|
||||
*--_RNext = static_cast<_Elem>('0' + _UVal_trunc % 10);
|
||||
_UVal_trunc /= 10;
|
||||
} while (_UVal_trunc != 0);
|
||||
return _RNext;
|
||||
}
|
||||
|
||||
template <class _Elem, class _Ty>
|
||||
_NODISCARD basic_string<_Elem> _Integral_to_string(const _Ty _Val) {
|
||||
// convert _Val to string
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <__msvc_chrono.hpp>
|
||||
#include <memory>
|
||||
#include <process.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <xthreads.h>
|
||||
|
||||
|
@ -19,9 +18,9 @@
|
|||
#include <stop_token>
|
||||
#endif // _HAS_CXX20
|
||||
|
||||
#if _HAS_CXX23
|
||||
#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
|
||||
#include <format>
|
||||
#endif // _HAS_CXX23
|
||||
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
|
||||
|
||||
#ifdef _M_CEE_PURE
|
||||
#error <thread> is not supported when compiling with /clr:pure.
|
||||
|
@ -297,7 +296,8 @@ basic_ostream<_Ch, _Tr>& operator<<(basic_ostream<_Ch, _Tr>& _Str, thread::id _I
|
|||
}
|
||||
|
||||
#if _HAS_CXX23 && defined(__cpp_lib_concepts)
|
||||
// Per LWG-3997, the _CharT template parameter is constrained to supported character types.
|
||||
// Per LWG-3997, `_CharT` in library-provided `formatter` specializations is
|
||||
// constrained to character types supported by `format`.
|
||||
template <_Format_supported_charT _CharT>
|
||||
struct formatter<thread::id, _CharT> {
|
||||
private:
|
||||
|
@ -305,7 +305,7 @@ private:
|
|||
|
||||
public:
|
||||
constexpr _Pc::iterator parse(_Pc& _Parse_ctx) {
|
||||
return _Impl.parse(_Parse_ctx);
|
||||
return _Impl._Parse(_Parse_ctx);
|
||||
}
|
||||
|
||||
template <class _FormatContext>
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
#include <xpolymorphic_allocator.h>
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
|
||||
#include <__msvc_formatter.hpp>
|
||||
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
|
||||
|
||||
#pragma pack(push, _CRT_PACKING)
|
||||
#pragma warning(push, _STL_WARNING_LEVEL)
|
||||
#pragma warning(disable : _STL_DISABLED_WARNINGS)
|
||||
|
@ -3585,6 +3589,26 @@ namespace pmr {
|
|||
} // namespace pmr
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
|
||||
template <class _Ty, class _CharT>
|
||||
requires _Is_specialization_v<_Ty, _Vb_reference>
|
||||
struct formatter<_Ty, _CharT> {
|
||||
private:
|
||||
formatter<bool, _CharT> _Underlying;
|
||||
|
||||
public:
|
||||
template <class _ParseContext>
|
||||
constexpr _ParseContext::iterator parse(_ParseContext& _Ctx) {
|
||||
return _Underlying.parse(_Ctx);
|
||||
}
|
||||
|
||||
template <class _FormatContext>
|
||||
_FormatContext::iterator format(const _Ty& _Ref, _FormatContext& _Ctx) const {
|
||||
return _Underlying.format(_Ref, _Ctx);
|
||||
}
|
||||
};
|
||||
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
|
||||
|
||||
template <class _Alloc, bool _RequiresMutable>
|
||||
_INLINE_VAR constexpr bool _Is_vb_iterator<_Vb_iterator<_Alloc>, _RequiresMutable> = true;
|
||||
|
||||
|
|
|
@ -2614,6 +2614,38 @@ struct _Is_transparent : bool_constant<_Is_transparent_v<_Ty>> {};
|
|||
template <class _Ty>
|
||||
concept _Transparent = _Is_transparent_v<_Ty>;
|
||||
#endif // defined(__cpp_lib_concepts)
|
||||
|
||||
template <class _Elem, class _UTy>
|
||||
_NODISCARD _Elem* _UIntegral_to_buff(_Elem* _RNext, _UTy _UVal) { // used by both to_string and thread::id output
|
||||
// format _UVal into buffer *ending at* _RNext
|
||||
static_assert(is_unsigned_v<_UTy>, "_UTy must be unsigned");
|
||||
|
||||
#ifdef _WIN64
|
||||
auto _UVal_trunc = _UVal;
|
||||
#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv
|
||||
|
||||
constexpr bool _Big_uty = sizeof(_UTy) > 4;
|
||||
if constexpr (_Big_uty) { // For 64-bit numbers, work in chunks to avoid 64-bit divisions.
|
||||
while (_UVal > 0xFFFFFFFFU) {
|
||||
auto _UVal_chunk = static_cast<unsigned long>(_UVal % 1000000000);
|
||||
_UVal /= 1000000000;
|
||||
|
||||
for (int _Idx = 0; _Idx != 9; ++_Idx) {
|
||||
*--_RNext = static_cast<_Elem>('0' + _UVal_chunk % 10);
|
||||
_UVal_chunk /= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto _UVal_trunc = static_cast<unsigned long>(_UVal);
|
||||
#endif // ^^^ !defined(_WIN64) ^^^
|
||||
|
||||
do {
|
||||
*--_RNext = static_cast<_Elem>('0' + _UVal_trunc % 10);
|
||||
_UVal_trunc /= 10;
|
||||
} while (_UVal_trunc != 0);
|
||||
return _RNext;
|
||||
}
|
||||
_STD_END
|
||||
|
||||
#pragma pop_macro("new")
|
||||
|
|
|
@ -602,6 +602,7 @@ tests\P2286R8_text_formatting_escaping
|
|||
tests\P2286R8_text_formatting_escaping_legacy_text_encoding
|
||||
tests\P2286R8_text_formatting_escaping_utf8
|
||||
tests\P2286R8_text_formatting_formattable
|
||||
tests\P2286R8_text_formatting_vector_bool_reference
|
||||
tests\P2302R4_ranges_alg_contains
|
||||
tests\P2302R4_ranges_alg_contains_subrange
|
||||
tests\P2321R2_proxy_reference
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <array>
|
||||
#include <chrono>
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <format>
|
||||
#include <forward_list>
|
||||
|
@ -52,6 +53,28 @@ concept encoded_character_type = same_as<CharT, char>
|
|||
#endif // defined(__cpp_char8_t)
|
||||
|| same_as<CharT, char16_t> || same_as<CharT, char32_t> || same_as<CharT, wchar_t>;
|
||||
|
||||
template <class T>
|
||||
struct alternative_allocator {
|
||||
using value_type = T;
|
||||
|
||||
alternative_allocator() = default;
|
||||
template <class U>
|
||||
constexpr alternative_allocator(const alternative_allocator<U>&) noexcept {}
|
||||
|
||||
T* allocate(size_t n) {
|
||||
return allocator<T>{}.allocate(n);
|
||||
}
|
||||
|
||||
void deallocate(T* p, size_t n) {
|
||||
allocator<T>{}.deallocate(p, n);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool operator==(const alternative_allocator<U>&) const noexcept {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class CharT>
|
||||
void assert_is_not_formattable() {
|
||||
static_assert(!formattable<T, CharT>);
|
||||
|
@ -179,6 +202,22 @@ void test_P2693() {
|
|||
}
|
||||
}
|
||||
|
||||
template <class CharT, class Vector>
|
||||
void test_P2286_vector_bool() {
|
||||
assert_is_formattable<typename Vector::reference, CharT>();
|
||||
|
||||
// The const_reference shall be bool.
|
||||
assert_is_formattable<typename Vector::const_reference, CharT>();
|
||||
}
|
||||
|
||||
// Tests for P2286 Formatting ranges
|
||||
template <class CharT>
|
||||
void test_P2286() {
|
||||
test_P2286_vector_bool<CharT, vector<bool>>();
|
||||
test_P2286_vector_bool<CharT, pmr::vector<bool>>();
|
||||
test_P2286_vector_bool<CharT, vector<bool, alternative_allocator<bool>>>();
|
||||
}
|
||||
|
||||
// Tests volatile qualified objects are no longer formattable.
|
||||
template <class CharT>
|
||||
void test_LWG3631() {
|
||||
|
@ -313,6 +352,7 @@ void test() {
|
|||
test_P0645<CharT>();
|
||||
test_P1361<CharT>();
|
||||
test_P2693<CharT>();
|
||||
test_P2286<CharT>();
|
||||
test_LWG3631<CharT>();
|
||||
test_abstract_class<CharT>();
|
||||
test_disabled<CharT>();
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\concepts_latest_matrix.lst
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <format>
|
||||
#include <locale>
|
||||
#include <memory>
|
||||
#include <memory_resource>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <test_format_support.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define STR(Str) TYPED_LITERAL(CharT, Str)
|
||||
|
||||
template <class T>
|
||||
struct alternative_allocator {
|
||||
using value_type = T;
|
||||
|
||||
alternative_allocator() = default;
|
||||
template <class U>
|
||||
constexpr alternative_allocator(const alternative_allocator<U>&) noexcept {}
|
||||
|
||||
T* allocate(size_t n) {
|
||||
return allocator<T>{}.allocate(n);
|
||||
}
|
||||
|
||||
void deallocate(T* p, size_t n) {
|
||||
allocator<T>{}.deallocate(p, n);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool operator==(const alternative_allocator<U>&) const noexcept {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEFAULT_IDL_SETTING 2
|
||||
#else
|
||||
#define DEFAULT_IDL_SETTING 0
|
||||
#endif
|
||||
|
||||
#if !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL_SETTING
|
||||
template <class CharT>
|
||||
struct yes_no_punct : numpunct<CharT> {
|
||||
basic_string<CharT> do_truename() const override {
|
||||
return STR("yes");
|
||||
}
|
||||
|
||||
basic_string<CharT> do_falsename() const override {
|
||||
return STR("no");
|
||||
}
|
||||
};
|
||||
#endif // !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL_SETTING
|
||||
|
||||
template <class CharT, class Alloc>
|
||||
void test_formatting_vector_bool_reference() {
|
||||
vector<bool, Alloc> vb{false, true};
|
||||
|
||||
assert(format(STR("{}, {}"), vb[0], vb[1]) == format(STR("{}, {}"), false, true));
|
||||
assert(format(STR("{:}, {:}"), vb[0], vb[1]) == format(STR("{:}, {:}"), false, true));
|
||||
assert(format(STR("{:d}, {:x}"), vb[0], vb[1]) == format(STR("{:d}, {:x}"), false, true));
|
||||
|
||||
#if !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL_SETTING
|
||||
locale loc{locale::classic(), new yes_no_punct<CharT>};
|
||||
|
||||
assert(format(loc, STR("{:L}"), vb[1]) == STR("yes"));
|
||||
assert(format(loc, STR("{:L}"), vb[0]) == STR("no"));
|
||||
#endif // !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL_SETTING
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_formatting_vector_bool_reference<char, allocator<bool>>();
|
||||
test_formatting_vector_bool_reference<char, pmr::polymorphic_allocator<bool>>();
|
||||
test_formatting_vector_bool_reference<char, alternative_allocator<bool>>();
|
||||
|
||||
test_formatting_vector_bool_reference<wchar_t, allocator<bool>>();
|
||||
test_formatting_vector_bool_reference<wchar_t, pmr::polymorphic_allocator<bool>>();
|
||||
test_formatting_vector_bool_reference<wchar_t, alternative_allocator<bool>>();
|
||||
}
|
Загрузка…
Ссылка в новой задаче