[libc++][format] Improves CTAD.
This partly reverts D133535 and enables CTAD for more parts in format. Reviewed By: ldionne, #libc Differential Revision: https://reviews.llvm.org/D135292
This commit is contained in:
parent
f4ad1b6f69
commit
261b5abf72
|
@ -1195,13 +1195,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
|
|||
# endif
|
||||
# endif
|
||||
|
||||
// There are a handful of standard library types that are intended to support CTAD but don't need any
|
||||
// explicit deduction guides to do so. This macro is used to mark them as such, which suppresses the
|
||||
// '-Wctad-maybe-unsupported' compiler warning when CTAD is used in user code with these classes.
|
||||
// There are a handful of public standard library types that are intended to
|
||||
// support CTAD but don't need any explicit deduction guides to do so. This
|
||||
// macro is used to mark them as such, which suppresses the
|
||||
// '-Wctad-maybe-unsupported' compiler warning when CTAD is used in user code
|
||||
// with these classes.
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) \
|
||||
template <class _Tag = void> \
|
||||
_ClassName(typename _Tag::__allow_ctad) -> _ClassName<_Tag>
|
||||
# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) \
|
||||
template <class ..._Tag> \
|
||||
_ClassName(typename _Tag::__allow_ctad...) -> _ClassName<_Tag...>
|
||||
#else
|
||||
# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "")
|
||||
#endif
|
||||
|
|
|
@ -50,8 +50,7 @@ __format_context_create(
|
|||
_OutIt __out_it,
|
||||
basic_format_args<basic_format_context<_OutIt, _CharT>> __args,
|
||||
optional<_VSTD::locale>&& __loc = nullopt) {
|
||||
return _VSTD::basic_format_context<_OutIt, _CharT>(_VSTD::move(__out_it), __args,
|
||||
_VSTD::move(__loc));
|
||||
return _VSTD::basic_format_context(_VSTD::move(__out_it), __args, _VSTD::move(__loc));
|
||||
}
|
||||
#else
|
||||
template <class _OutIt, class _CharT>
|
||||
|
@ -59,7 +58,7 @@ _LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
|
|||
__format_context_create(
|
||||
_OutIt __out_it,
|
||||
basic_format_args<basic_format_context<_OutIt, _CharT>> __args) {
|
||||
return _VSTD::basic_format_context<_OutIt, _CharT>(_VSTD::move(__out_it), __args);
|
||||
return _VSTD::basic_format_context(_VSTD::move(__out_it), __args);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -143,6 +142,7 @@ private:
|
|||
: __out_it_(_VSTD::move(__out_it)), __args_(__args) {}
|
||||
#endif
|
||||
};
|
||||
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_context);
|
||||
|
||||
#endif //_LIBCPP_STD_VER > 17
|
||||
|
||||
|
|
|
@ -239,8 +239,7 @@ template <class _CharT, class _ParseCtx, class _Ctx>
|
|||
_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
|
||||
__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
|
||||
_ParseCtx& __parse_ctx, _Ctx& __ctx) {
|
||||
__format::__parse_number_result<_CharT> __r =
|
||||
__format::__parse_arg_id(__begin, __end, __parse_ctx);
|
||||
__format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx);
|
||||
|
||||
bool __parse = *__r.__ptr == _CharT(':');
|
||||
switch (*__r.__ptr) {
|
||||
|
@ -392,15 +391,12 @@ requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
|
|||
_OutIt __out_it, basic_string_view<_CharT> __fmt,
|
||||
basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
|
||||
if constexpr (same_as<_OutIt, _FormatOutIt>)
|
||||
return _VSTD::__format::__vformat_to(
|
||||
basic_format_parse_context<_CharT>{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(_VSTD::move(__out_it), __args));
|
||||
return _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(_VSTD::move(__out_it), __args));
|
||||
else {
|
||||
__format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
|
||||
_VSTD::__format::__vformat_to(
|
||||
basic_format_parse_context<_CharT>{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(__buffer.__make_output_iterator(),
|
||||
__args));
|
||||
_VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
|
||||
return _VSTD::move(__buffer).__out_it();
|
||||
}
|
||||
}
|
||||
|
@ -473,7 +469,7 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it,
|
|||
basic_string_view<_CharT> __fmt,
|
||||
basic_format_args<_Context> __args) {
|
||||
__format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
|
||||
_VSTD::__format::__vformat_to(basic_format_parse_context<_CharT>{__fmt, __args.__size()},
|
||||
_VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
|
||||
return _VSTD::move(__buffer).__result();
|
||||
}
|
||||
|
@ -496,7 +492,7 @@ format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args
|
|||
template <class _CharT>
|
||||
_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
|
||||
__format::__formatted_size_buffer<_CharT> __buffer;
|
||||
_VSTD::__format::__vformat_to(basic_format_parse_context<_CharT>{__fmt, __args.__size()},
|
||||
_VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
|
||||
return _VSTD::move(__buffer).__result();
|
||||
}
|
||||
|
@ -524,15 +520,13 @@ requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
|
|||
basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
|
||||
if constexpr (same_as<_OutIt, _FormatOutIt>)
|
||||
return _VSTD::__format::__vformat_to(
|
||||
basic_format_parse_context<_CharT>{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(_VSTD::move(__out_it), __args,
|
||||
_VSTD::move(__loc)));
|
||||
basic_format_parse_context{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(_VSTD::move(__out_it), __args, _VSTD::move(__loc)));
|
||||
else {
|
||||
__format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
|
||||
_VSTD::__format::__vformat_to(
|
||||
basic_format_parse_context<_CharT>{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(__buffer.__make_output_iterator(),
|
||||
__args, _VSTD::move(__loc)));
|
||||
basic_format_parse_context{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
|
||||
return _VSTD::move(__buffer).__out_it();
|
||||
}
|
||||
}
|
||||
|
@ -610,7 +604,7 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it,
|
|||
basic_format_args<_Context> __args) {
|
||||
__format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
|
||||
_VSTD::__format::__vformat_to(
|
||||
basic_format_parse_context<_CharT>{__fmt, __args.__size()},
|
||||
basic_format_parse_context{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
|
||||
return _VSTD::move(__buffer).__result();
|
||||
}
|
||||
|
@ -637,7 +631,7 @@ template <class _CharT>
|
|||
_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
|
||||
__format::__formatted_size_buffer<_CharT> __buffer;
|
||||
_VSTD::__format::__vformat_to(
|
||||
basic_format_parse_context<_CharT>{__fmt, __args.__size()},
|
||||
basic_format_parse_context{__fmt, __args.__size()},
|
||||
_VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
|
||||
return _VSTD::move(__buffer).__result();
|
||||
}
|
||||
|
|
|
@ -88,6 +88,7 @@ private:
|
|||
size_t __next_arg_id_;
|
||||
size_t __num_args_;
|
||||
};
|
||||
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_parse_context);
|
||||
|
||||
using format_parse_context = basic_format_parse_context<char>;
|
||||
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
|
|
|
@ -32,6 +32,9 @@ struct _LIBCPP_TEMPLATE_VIS __parse_number_result {
|
|||
uint32_t __value;
|
||||
};
|
||||
|
||||
template <class _CharT>
|
||||
__parse_number_result(const _CharT*, uint32_t) -> __parse_number_result<_CharT>;
|
||||
|
||||
template <class _CharT>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT>
|
||||
__parse_number(const _CharT* __begin, const _CharT* __end);
|
||||
|
|
|
@ -54,8 +54,7 @@ __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
|
|||
if (__begin == __end)
|
||||
__throw_format_error("End of input while parsing format-spec arg-id");
|
||||
|
||||
__format::__parse_number_result<_CharT> __r =
|
||||
__format::__parse_arg_id(__begin, __end, __parse_ctx);
|
||||
__format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx);
|
||||
|
||||
if (__r.__ptr == __end || *__r.__ptr != _CharT('}'))
|
||||
__throw_format_error("Invalid arg-id");
|
||||
|
@ -422,7 +421,7 @@ private:
|
|||
__throw_format_error("A format-spec width field shouldn't have a leading zero");
|
||||
|
||||
if (*__begin == _CharT('{')) {
|
||||
__format::__parse_number_result<_CharT> __r = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx);
|
||||
__format::__parse_number_result __r = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx);
|
||||
__width_as_arg_ = true;
|
||||
__width_ = __r.__value;
|
||||
__begin = __r.__ptr;
|
||||
|
@ -432,7 +431,7 @@ private:
|
|||
if (*__begin < _CharT('0') || *__begin > _CharT('9'))
|
||||
return false;
|
||||
|
||||
__format::__parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end);
|
||||
__format::__parse_number_result __r = __format::__parse_number(__begin, __end);
|
||||
__width_ = __r.__value;
|
||||
_LIBCPP_ASSERT(__width_ != 0, "A zero value isn't allowed and should be impossible, "
|
||||
"due to validations in this function");
|
||||
|
@ -450,7 +449,7 @@ private:
|
|||
__throw_format_error("End of input while parsing format-spec precision");
|
||||
|
||||
if (*__begin == _CharT('{')) {
|
||||
__format::__parse_number_result<_CharT> __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx);
|
||||
__format::__parse_number_result __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx);
|
||||
__precision_as_arg_ = true;
|
||||
__precision_ = __arg_id.__value;
|
||||
__begin = __arg_id.__ptr;
|
||||
|
@ -460,7 +459,7 @@ private:
|
|||
if (*__begin < _CharT('0') || *__begin > _CharT('9'))
|
||||
__throw_format_error("The format-spec precision field doesn't contain a value or arg-id");
|
||||
|
||||
__format::__parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end);
|
||||
__format::__parse_number_result __r = __format::__parse_number(__begin, __end);
|
||||
__precision_ = __r.__value;
|
||||
__precision_as_arg_ = false;
|
||||
__begin = __r.__ptr;
|
||||
|
@ -702,6 +701,9 @@ struct __column_width_result {
|
|||
const _CharT* __last_;
|
||||
};
|
||||
|
||||
template <class _CharT>
|
||||
__column_width_result(size_t, const _CharT*) -> __column_width_result<_CharT>;
|
||||
|
||||
/// Since a column width can be two it's possible that the requested column
|
||||
/// width can't be achieved. Depending on the intended usage the policy can be
|
||||
/// selected.
|
||||
|
@ -879,7 +881,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_
|
|||
}
|
||||
|
||||
ptrdiff_t __ascii_size = __it - __str.begin();
|
||||
__column_width_result<_CharT> __result =
|
||||
__column_width_result __result =
|
||||
__detail::__estimate_column_width_grapheme_clustering(__it, __str.end(), __maximum, __rounding);
|
||||
|
||||
__result.__width_ += __ascii_size;
|
||||
|
|
|
@ -24,8 +24,7 @@ void test(
|
|||
std::basic_format_args<std::basic_format_context<OutIt, CharT>> args) {
|
||||
{
|
||||
std::basic_string<CharT> str[3];
|
||||
std::basic_format_context<OutIt, CharT> context =
|
||||
test_format_context_create(OutIt{str[0]}, args);
|
||||
std::basic_format_context context = test_format_context_create(OutIt{str[0]}, args);
|
||||
context.out() = CharT('a');
|
||||
context.advance_to(OutIt{str[1]});
|
||||
context.out() = CharT('b');
|
||||
|
|
|
@ -28,8 +28,7 @@ void test() {
|
|||
std::basic_format_args args = store;
|
||||
|
||||
std::basic_string<CharT> output;
|
||||
const std::basic_format_context<OutIt, CharT> context =
|
||||
test_format_context_create(OutIt{output}, args);
|
||||
const std::basic_format_context context = test_format_context_create(OutIt{output}, args);
|
||||
LIBCPP_ASSERT(args.__size() == 4);
|
||||
ASSERT_NOEXCEPT(context.arg(0));
|
||||
for (size_t i = 0, e = args.__size(); i != e; ++i) {
|
||||
|
|
|
@ -55,7 +55,7 @@ void test() {
|
|||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args);
|
||||
std::basic_format_context context = test_format_context_create(out_it, args);
|
||||
LIBCPP_ASSERT(args.__size() == 4);
|
||||
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
|
@ -79,7 +79,7 @@ void test() {
|
|||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args, en_US);
|
||||
std::basic_format_context context = test_format_context_create(out_it, args, en_US);
|
||||
|
||||
LIBCPP_ASSERT(args.__size() == 4);
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
|
@ -99,7 +99,7 @@ void test() {
|
|||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args, fr_FR);
|
||||
std::basic_format_context context = test_format_context_create(out_it, args, fr_FR);
|
||||
|
||||
LIBCPP_ASSERT(args.__size() == 4);
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
|
|
|
@ -39,7 +39,7 @@ void test() {
|
|||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args, en_US);
|
||||
std::basic_format_context context = test_format_context_create(out_it, args, en_US);
|
||||
assert(args.__size() == 4);
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
assert(test_basic_format_arg(context.arg(1), CharT('a')));
|
||||
|
@ -58,7 +58,7 @@ void test() {
|
|||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args, fr_FR);
|
||||
std::basic_format_context context = test_format_context_create(out_it, args, fr_FR);
|
||||
assert(args.__size() == 4);
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
assert(test_basic_format_arg(context.arg(1), CharT('a')));
|
||||
|
|
|
@ -25,7 +25,7 @@ void test(
|
|||
{
|
||||
std::basic_string<CharT> str;
|
||||
OutIt out_it{str};
|
||||
std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args);
|
||||
std::basic_format_context context = test_format_context_create(out_it, args);
|
||||
context.out() = CharT('a');
|
||||
context.out() = CharT('b');
|
||||
context.out() = CharT('c');
|
||||
|
|
|
@ -35,7 +35,7 @@ constexpr void test(const CharT* fmt) {
|
|||
}
|
||||
{
|
||||
std::basic_string_view view{fmt};
|
||||
std::basic_format_parse_context<CharT> context(view);
|
||||
std::basic_format_parse_context context(view);
|
||||
|
||||
context.advance_to(context.begin() + 1);
|
||||
assert(std::to_address(context.begin()) == fmt + 1);
|
||||
|
|
|
@ -28,7 +28,7 @@ constexpr void test(const CharT* fmt) {
|
|||
}
|
||||
{
|
||||
std::basic_string_view view{fmt};
|
||||
std::basic_format_parse_context<CharT> context(view);
|
||||
std::basic_format_parse_context context(view);
|
||||
assert(context.begin() == view.begin());
|
||||
ASSERT_NOEXCEPT(context.begin());
|
||||
}
|
||||
|
|
|
@ -39,10 +39,8 @@ constexpr void test(const CharT* fmt) {
|
|||
static_assert(
|
||||
!std::is_move_assignable_v<std::basic_format_parse_context<CharT> >);
|
||||
|
||||
ASSERT_NOEXCEPT(
|
||||
std::basic_format_parse_context<CharT>{std::basic_string_view<CharT>{}});
|
||||
ASSERT_NOEXCEPT(
|
||||
std::basic_format_parse_context<CharT>{std::basic_string_view<CharT>{}, 42});
|
||||
ASSERT_NOEXCEPT(std::basic_format_parse_context{std::basic_string_view<CharT>{}});
|
||||
ASSERT_NOEXCEPT(std::basic_format_parse_context{std::basic_string_view<CharT>{}, 42});
|
||||
|
||||
{
|
||||
std::basic_format_parse_context<CharT> context(fmt);
|
||||
|
@ -51,7 +49,7 @@ constexpr void test(const CharT* fmt) {
|
|||
}
|
||||
{
|
||||
std::basic_string_view view{fmt};
|
||||
std::basic_format_parse_context<CharT> context(view);
|
||||
std::basic_format_parse_context context(view);
|
||||
assert(context.begin() == view.begin());
|
||||
assert(context.end() == view.end());
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ constexpr void test(const CharT* fmt) {
|
|||
}
|
||||
{
|
||||
std::basic_string_view view{fmt};
|
||||
std::basic_format_parse_context<CharT> context(view);
|
||||
std::basic_format_parse_context context(view);
|
||||
assert(context.end() == view.end());
|
||||
ASSERT_NOEXCEPT(context.end());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue