[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:
parent
96c9913332
commit
ca055bbec7
@ -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","","",""
|
||||
|
|
@ -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
|
||||
|
@ -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>();
|
||||
|
@ -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); };
|
||||
|
Loading…
x
Reference in New Issue
Block a user