[libc++][format] LWG4061: Should std::basic_format_context be default-constructible/copyable/movable? (#97251)

See [LWG4061](https://cplusplus.github.io/LWG/issue4061) and
[P3341R0](https://wg21.link/p3341r0). Effectively reverts commit
36ce0c3b1e581ca310ae7d0cbc6af002cc5d0251.


`libcxx/test/std/utilities/format/format.functions/bug_81590.compile.pass.cpp`
has a `format` function that unexpectedly takes the
`basic_format_context` by value, which is made ill-formed by LWG4061.
This PR changes the function to take the context by reference.
This commit is contained in:
A. Jiang 2024-07-09 18:23:50 +08:00 committed by GitHub
parent 96c9913332
commit ca055bbec7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 20 additions and 9 deletions

View File

@ -64,7 +64,7 @@
"","","","","",""
"`3944 <https://wg21.link/LWG3944>`__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","St. Louis June 2024","","","|format|"
"`4060 <https://wg21.link/LWG4060>`__","``submdspan`` preconditions do not forbid creating invalid pointer","St. Louis June 2024","","",""
"`4061 <https://wg21.link/LWG4061>`__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","St. Louis June 2024","","","|format|"
"`4061 <https://wg21.link/LWG4061>`__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","St. Louis June 2024","|Complete|","19.0","|format|"
"`4071 <https://wg21.link/LWG4071>`__","``reference_wrapper`` comparisons are not SFINAE-friendly","St. Louis June 2024","|Complete|","19.0",""
"`4074 <https://wg21.link/LWG4074>`__","``compatible-joinable-ranges`` is underconstrained","St. Louis June 2024","","","|ranges|"
"`4076 <https://wg21.link/LWG4076>`__","``concat_view`` should be freestanding","St. Louis June 2024","","",""

1 Issue # Issue Name Meeting Status First released version Labels
64
65 `3944 <https://wg21.link/LWG3944>`__ Formatters converting sequences of ``char`` to sequences of ``wchar_t`` St. Louis June 2024 |format|
66 `4060 <https://wg21.link/LWG4060>`__ ``submdspan`` preconditions do not forbid creating invalid pointer St. Louis June 2024
67 `4061 <https://wg21.link/LWG4061>`__ Should ``std::basic_format_context`` be default-constructible/copyable/movable? St. Louis June 2024 |Complete| 19.0 |format|
68 `4071 <https://wg21.link/LWG4071>`__ ``reference_wrapper`` comparisons are not SFINAE-friendly St. Louis June 2024 |Complete| 19.0
69 `4074 <https://wg21.link/LWG4074>`__ ``compatible-joinable-ranges`` is underconstrained St. Louis June 2024 |ranges|
70 `4076 <https://wg21.link/LWG4076>`__ ``concat_view`` should be freestanding St. Louis June 2024

View File

@ -131,6 +131,9 @@ private:
_LIBCPP_HIDE_FROM_ABI explicit basic_format_context(_OutIt __out_it, basic_format_args<basic_format_context> __args)
: __out_it_(std::move(__out_it)), __args_(__args) {}
# endif
basic_format_context(const basic_format_context&) = delete;
basic_format_context& operator=(const basic_format_context&) = delete;
};
// A specialization for __retarget_buffer

View File

@ -112,19 +112,27 @@ void test() {
#endif
}
// std::back_insert_iterator<std::string>, copyable
static_assert(std::is_copy_constructible_v<std::basic_format_context<std::back_insert_iterator<std::string>, char>>);
static_assert(std::is_copy_assignable_v<std::basic_format_context<std::back_insert_iterator<std::string>, char>>);
// The default constructor is suppressed by the deleted copy operations.
// The move operations are implicitly deleted due to the deleted copy operations.
static_assert(std::is_move_constructible_v<std::basic_format_context<std::back_insert_iterator<std::string>, char>>);
static_assert(std::is_move_assignable_v<std::basic_format_context<std::back_insert_iterator<std::string>, char>>);
// std::back_insert_iterator<std::string>, copyable
static_assert(
!std::is_default_constructible_v<std::basic_format_context<std::back_insert_iterator<std::string>, char>>);
static_assert(!std::is_copy_constructible_v<std::basic_format_context<std::back_insert_iterator<std::string>, char>>);
static_assert(!std::is_copy_assignable_v<std::basic_format_context<std::back_insert_iterator<std::string>, char>>);
static_assert(!std::is_move_constructible_v<std::basic_format_context<std::back_insert_iterator<std::string>, char>>);
static_assert(!std::is_move_assignable_v<std::basic_format_context<std::back_insert_iterator<std::string>, char>>);
// cpp20_output_iterator, move only
static_assert(!std::is_default_constructible_v<std::basic_format_context<cpp20_output_iterator<int*>, char>>);
static_assert(!std::is_copy_constructible_v<std::basic_format_context<cpp20_output_iterator<int*>, char>>);
static_assert(!std::is_copy_assignable_v<std::basic_format_context<cpp20_output_iterator<int*>, char>>);
static_assert(std::is_move_constructible_v<std::basic_format_context<cpp20_output_iterator<int*>, char>>);
static_assert(std::is_move_assignable_v<std::basic_format_context<cpp20_output_iterator<int*>, char>>);
static_assert(!std::is_move_constructible_v<std::basic_format_context<cpp20_output_iterator<int*>, char>>);
static_assert(!std::is_move_assignable_v<std::basic_format_context<cpp20_output_iterator<int*>, char>>);
int main(int, char**) {
test<std::back_insert_iterator<std::basic_string<char>>, char>();

View File

@ -25,7 +25,7 @@ struct X : std::variant<X*> {
template <>
struct std::formatter<X, char> : std::formatter<std::string, char> {
static constexpr auto format(const X& x, auto ctx) {
static constexpr auto format(const X& x, auto& ctx) {
if (!x.p)
return ctx.out();
auto m = [&](const X* t) { return std::format_to(ctx.out(), "{}", *t); };