LWG-3539 was already implemented but not marked as done.
LWG-3567 is implemented in this commit.
Reviewed By: ldionne, #libc
Differential Revision: https://reviews.llvm.org/D112368
`3532 <https://wg21.link/LWG3532>`__,"``split_view<V, P>::inner-iterator<true>::operator++(int)`` should depend on ``Base``","June 2021","","","|ranges|"
`3533 <https://wg21.link/LWG3533>`__,"Make ``base() const &`` consistent across iterator wrappers that supports ``input_iterators``","June 2021","|Complete|","14.0","|ranges|"
`3536 <https://wg21.link/LWG3536>`__,"Should ``chrono::from_stream()`` assign zero to duration for failure?","June 2021","","","|chrono|"
-`3539 <https://wg21.link/LWG3539>`__,"``format_to`` must not copy models of ``output_iterator<const charT&>``","June 2021","","","|format|"
+`3539 <https://wg21.link/LWG3539>`__,"``format_to`` must not copy models of ``output_iterator<const charT&>``","June 2021","|Complete|","14.0","|format|"
`3540 <https://wg21.link/LWG3540>`__,"ยง[format.arg] There should be no const in ``basic_format_arg(const T* p)``","June 2021","|Complete|","14.0","|format|"
`3541 <https://wg21.link/LWG3541>`__,"``indirectly_readable_traits`` should be SFINAE-friendly for all types","June 2021","|Complete|","14.0","|ranges|"
`3542 <https://wg21.link/LWG3542>`__,"``basic_format_arg`` mishandles ``basic_string_view`` with custom traits","June 2021","|Complete|","14.0","|format|"
`3561 <https://wg21.link/LWG3561>`__,"Issue with internal counter in ``discard_block_engine``","October 2021","",""
`3563 <https://wg21.link/LWG3563>`__,"``keys_view`` example is broken","October 2021","","","|ranges|"
`3566 <https://wg21.link/LWG3566>`__,"Constraint recursion for ``operator<=>(optional<T>, U)``","October 2021","","","|spaceship|"
-`3567 <https://wg21.link/LWG3567>`__,"Formatting move-only iterators take two","October 2021","","","|format|"
+`3567 <https://wg21.link/LWG3567>`__,"Formatting move-only iterators take two","October 2021","|Complete|","16.0","|format|"
`3568 <https://wg21.link/LWG3568>`__,"``basic_istream_view`` needs to initialize ``value_``","October 2021","|Complete|","16.0","|ranges|"
`3570 <https://wg21.link/LWG3570>`__,"``basic_osyncstream::emit`` should be an unformatted output function","October 2021","",""
`3571 <https://wg21.link/LWG3571>`__,"``flush_emit`` should set ``badbit`` if the ``emit`` call fails","October 2021","",""
#include <__algorithm/fill_n.h>
#include <__algorithm/max.h>
#include <__algorithm/min.h>
+#include <__algorithm/ranges_copy_n.h>
#include <__algorithm/transform.h>
#include <__algorithm/unwrap_iter.h>
#include <__config>
_LIBCPP_HIDE_FROM_ABI explicit __writer_iterator(_OutIt __out_it)
: __out_it_{_VSTD::move(__out_it)} {}
- _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() { return __out_it_; }
+ _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return std::move(__out_it_); }
_LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
- __out_it_ = _VSTD::copy_n(__ptr, __n, _VSTD::move(__out_it_));
+ __out_it_ = std::ranges::copy_n(__ptr, __n, std::move(__out_it_)).out;
}
private:
return *__loc_;
}
#endif
- _LIBCPP_HIDE_FROM_ABI iterator out() { return __out_it_; }
- _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = __it; }
+ _LIBCPP_HIDE_FROM_ABI iterator out() { return std::move(__out_it_); }
+ _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = std::move(__it); }
private:
iterator __out_it_;
#include "test_macros.h"
#include "test_format_context.h"
+#include "test_iterators.h"
template <class OutIt, class CharT>
void test(
std::basic_format_args<std::basic_format_context<OutIt, CharT>> args) {
{
- std::basic_string<CharT> str[3];
- 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');
- context.advance_to(OutIt{str[2]});
- context.out() = CharT('c');
+ std::basic_string<CharT> str[3] = {
+ std::basic_string<CharT>{1}, std::basic_string<CharT>{1}, std::basic_string<CharT>{1}};
+ std::basic_format_context context = test_format_context_create(OutIt{str[0].begin()}, args);
+ *context.out() = CharT('a');
+ context.advance_to(OutIt{str[1].begin()});
+ *context.out() = CharT('b');
+ context.advance_to(OutIt{str[2].begin()});
+ *context.out() = CharT('c');
assert(str[0].size() == 1);
assert(str[0].front() == CharT('a'));
void test() {
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<char>>, char>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<char>::iterator>, char>>()));
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<wchar_t>::iterator>, wchar_t>>()));
#endif
#ifndef TEST_HAS_NO_CHAR8_T
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<char8_t>>, char8_t>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<char8_t>::iterator>, char8_t>>()));
#endif
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<char16_t>>,
- char16_t>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<char16_t>::iterator>, char16_t>>()));
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<char32_t>>,
- char32_t>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<char32_t>::iterator>, char32_t>>()));
}
int main(int, char**) {
#include "test_macros.h"
#include "test_format_context.h"
+#include "test_iterators.h"
template <class OutIt, class CharT>
void test(
std::basic_format_args<std::basic_format_context<OutIt, CharT>> args) {
{
- std::basic_string<CharT> str;
- OutIt out_it{str};
- std::basic_format_context context = test_format_context_create(out_it, args);
- context.out() = CharT('a');
- context.out() = CharT('b');
- context.out() = CharT('c');
+ std::basic_string<CharT> str = std::basic_string<CharT>(3, CharT(' '));
+ std::basic_format_context context = test_format_context_create(OutIt{str.begin()}, args);
+
+ // Note this operation is moving the iterator
+ OutIt out_it = context.out();
+ *out_it++ = CharT('a');
+ *out_it++ = CharT('b');
+ *out_it++ = CharT('c');
assert(str.size() == 3);
assert(str[0] == CharT('a'));
void test() {
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<char>>, char>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<char>::iterator>, char>>()));
+
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<wchar_t>::iterator>, wchar_t>>()));
#endif
#ifndef TEST_HAS_NO_CHAR8_T
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<char8_t>>, char8_t>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<char8_t>::iterator>, char8_t>>()));
#endif
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<char16_t>>,
- char16_t>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<char16_t>::iterator>, char16_t>>()));
test(std::basic_format_args(
- std::make_format_args<std::basic_format_context<
- std::back_insert_iterator<std::basic_string<char32_t>>,
- char32_t>>()));
+ std::make_format_args<
+ std::basic_format_context<cpp20_output_iterator<std::basic_string<char32_t>::iterator>, char32_t>>()));
}
int main(int, char**) {
#include "format_tests.h"
#include "string_literal.h"
#include "test_format_string.h"
+#include "test_iterators.h"
auto test =
[]<class CharT, class... Args>(
{
assert(expected.size() < 4096 && "Update the size of the buffer.");
CharT out[4096];
- CharT* it = std::format_to(out, std::locale(), fmt, std::forward<Args>(args)...);
- assert(std::distance(out, it) == int(expected.size()));
+ cpp20_output_iterator<CharT*> it =
+ std::format_to(cpp20_output_iterator{out}, std::locale(), fmt, std::forward<Args>(args)...);
+ assert(std::distance(out, base(it)) == int(expected.size()));
// Convert to std::string since output contains '\0' for boolean tests.
- assert(std::basic_string<CharT>(out, it) == expected);
+ assert(std::basic_string<CharT>(out, base(it)) == expected);
}
};
#include "format_tests.h"
#include "string_literal.h"
#include "test_format_string.h"
+#include "test_iterators.h"
auto test =
[]<class CharT, class... Args>(
{
assert(expected.size() < 4096 && "Update the size of the buffer.");
CharT out[4096];
- CharT* it = std::format_to(out, fmt, std::forward<Args>(args)...);
- assert(std::distance(out, it) == int(expected.size()));
+ cpp20_output_iterator<CharT*> it = std::format_to(cpp20_output_iterator{out}, fmt, std::forward<Args>(args)...);
+ assert(std::distance(out, base(it)) == int(expected.size()));
// Convert to std::string since output contains '\0' for boolean tests.
- assert(std::basic_string<CharT>(out, it) == expected);
+ assert(std::basic_string<CharT>(out, base(it)) == expected);
}
};