[libcxx-commits] [libcxx] a09b1dc - [libc++][format] Adds formatter std::vector<bool>.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jan 19 08:58:10 PST 2023


Author: Mark de Wever
Date: 2023-01-19T17:58:05+01:00
New Revision: a09b1dc1f2c534cc8b870b5b7c9bc7f7682a1ed5

URL: https://github.com/llvm/llvm-project/commit/a09b1dc1f2c534cc8b870b5b7c9bc7f7682a1ed5
DIFF: https://github.com/llvm/llvm-project/commit/a09b1dc1f2c534cc8b870b5b7c9bc7f7682a1ed5.diff

LOG: [libc++][format] Adds formatter std::vector<bool>.

Implements parts of
- P2286R8 Formatting Ranges

Depends on D140653

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D141761

Added: 
    libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.format.pass.cpp
    libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h
    libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.vformat.pass.cpp
    libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.pass.cpp
    libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp

Modified: 
    libcxx/docs/Status/FormatPaper.csv
    libcxx/include/__bit_reference
    libcxx/include/vector
    libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv
index 10463c44ef8f..d80346e9d68c 100644
--- a/libcxx/docs/Status/FormatPaper.csv
+++ b/libcxx/docs/Status/FormatPaper.csv
@@ -34,4 +34,4 @@ Section,Description,Dependencies,Assignee,Status,First released version
 `[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: associative",,Mark de Wever,,
 `[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: container adaptors",,Mark de Wever,|Complete|,Clang 16
 `[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: ``pair`` and ``tuple``",,Mark de Wever,|Complete|,Clang 16
-`[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: ``vector<bool>``",,Mark de Wever,,
+`[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: ``vector<bool>``",,Mark de Wever,|Complete|,Clang 16

diff  --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference
index b954c1049377..26657491393d 100644
--- a/libcxx/include/__bit_reference
+++ b/libcxx/include/__bit_reference
@@ -55,6 +55,8 @@ class __bit_reference
     friend class __bit_const_reference<_Cp>;
     friend class __bit_iterator<_Cp, false>;
 public:
+    using __container = typename _Cp::__self;
+
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
     __bit_reference(const __bit_reference&) = default;
 

diff  --git a/libcxx/include/vector b/libcxx/include/vector
index e9d1b72171e7..4c939806dc12 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -267,6 +267,13 @@ template <class T, class Allocator, class Predicate>
 typename vector<T, Allocator>::size_type
 erase_if(vector<T, Allocator>& c, Predicate pred);    // C++20
 
+
+template<class T>
+ inline constexpr bool is-vector-bool-reference = see below;        // exposition only, since C++23
+
+template<class T, class charT> requires is-vector-bool-reference<T> // Since C++23
+ struct formatter<T, charT>;
+
 }  // std
 
 */
@@ -281,9 +288,11 @@ erase_if(vector<T, Allocator>& c, Predicate pred);    // C++20
 #include <__algorithm/unwrap_iter.h>
 #include <__assert> // all public C++ headers provide the assertion handler
 #include <__bit_reference>
+#include <__concepts/same_as.h>
 #include <__config>
 #include <__debug>
 #include <__format/enable_insertable.h>
+#include <__format/formatter.h>
 #include <__functional/hash.h>
 #include <__functional/unary_function.h>
 #include <__iterator/advance.h>
@@ -3312,6 +3321,27 @@ inline constexpr bool __format::__enable_insertable<vector<wchar_t>> = true;
 
 #endif // _LIBCPP_STD_VER > 17
 
+#if _LIBCPP_STD_VER > 20
+template <class _Tp, class CharT>
+// Since is-vector-bool-reference is only used once it's inlined here.
+  requires same_as<typename _Tp::__container, vector<bool, typename _Tp::__container::allocator_type>>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_Tp, CharT> {
+private:
+  formatter<bool, CharT> __underlying_;
+
+public:
+  template <class _ParseContext>
+  _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
+        return __underlying_.parse(__ctx);
+  }
+
+  template <class _FormatContext>
+  _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _Tp& __ref, _FormatContext& __ctx) const {
+        return __underlying_.format(__ref, __ctx);
+  }
+};
+#endif // _LIBCPP_STD_VER > 20
+
 _LIBCPP_END_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER > 14

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.format.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.format.pass.cpp
new file mode 100644
index 000000000000..61cbfea76de7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.format.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// <vector>
+
+// template<class T, class charT>
+//   requires is-vector-bool-reference<T>
+// struct formatter<T, charT>
+
+// template<class... Args>
+//   string format(format_string<Args...> fmt, Args&&... args);
+// template<class... Args>
+//   wstring format(wformat_string<Args...> fmt, Args&&... args);
+
+#include <format>
+#include <cassert>
+
+#include "format.functions.tests.h"
+#include "test_format_string.h"
+#include "test_macros.h"
+#include "assert_macros.h"
+
+auto test = []<class CharT, class... Args>(
+                std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
+  std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...);
+  TEST_REQUIRE(
+      out == expected,
+      test_concat_message("\nFormat string   ", fmt, "\nExpected output ", expected, "\nActual output   ", out, '\n'));
+};
+
+auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, Args&&...) {
+  // After P2216 most exceptions thrown by std::format become ill-formed.
+  // Therefore this tests does nothing.
+};
+
+int main(int, char**) {
+  format_tests<char>(test, test_exception);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  format_tests<wchar_t>(test, test_exception);
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h
new file mode 100644
index 000000000000..32b68b85f85a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h
@@ -0,0 +1,116 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_STD_CONTAINERS_SEQUENCES_VECTOR_BOOL_VECTOR_BOOL_FMT_FORMAT_FUNCTIONS_TESTS_H
+#define TEST_STD_CONTAINERS_SEQUENCES_VECTOR_BOOL_VECTOR_BOOL_FMT_FORMAT_FUNCTIONS_TESTS_H
+
+#include <vector>
+
+#include "format.functions.common.h"
+#include "test_macros.h"
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void format_tests(TestFunction check, ExceptionTest check_exception) {
+  std::vector input{true, true, false};
+
+  check(SV("[true, true, false]"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("[true, true, false]     "), SV("{:24}"), input);
+  check(SV("[true, true, false]*****"), SV("{:*<24}"), input);
+  check(SV("__[true, true, false]___"), SV("{:_^24}"), input);
+  check(SV("#####[true, true, false]"), SV("{:#>24}"), input);
+
+  check(SV("[true, true, false]     "), SV("{:{}}"), input, 24);
+  check(SV("[true, true, false]*****"), SV("{:*<{}}"), input, 24);
+  check(SV("__[true, true, false]___"), SV("{:_^{}}"), input, 24);
+  check(SV("#####[true, true, false]"), SV("{:#>{}}"), input, 24);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
+
+  // *** n
+  check(SV("__true, true, false___"), SV("{:_^22n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Only underlying has a format-spec
+  check(SV("[true   , true   , false  ]"), SV("{::7}"), input);
+  check(SV("[true***, true***, false**]"), SV("{::*<7}"), input);
+  check(SV("[_true__, _true__, _false_]"), SV("{::_^7}"), input);
+  check(SV("[:::true, :::true, ::false]"), SV("{:::>7}"), input);
+
+  check(SV("[true   , true   , false  ]"), SV("{::{}}"), input, 7);
+  check(SV("[true***, true***, false**]"), SV("{::*<{}}"), input, 7);
+  check(SV("[_true__, _true__, _false_]"), SV("{::_^{}}"), input, 7);
+  check(SV("[:::true, :::true, ::false]"), SV("{:::>{}}"), input, 7);
+
+  check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::-}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::+}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{:: }"), input);
+
+  check(SV("[1, 1, 0]"), SV("{::-d}"), input);
+  check(SV("[+1, +1, +0]"), SV("{::+d}"), input);
+  check(SV("[ 1,  1,  0]"), SV("{:: d}"), input);
+
+  // *** alternate form ***
+  check_exception("An alternate form field isn't allowed in this format-spec", SV("{::#}"), input);
+
+  check(SV("[0x1, 0x1, 0x0]"), SV("{::#x}"), input);
+
+  // *** zero-padding ***
+  check_exception("A zero-padding field isn't allowed in this format-spec", SV("{::05}"), input);
+
+  check(SV("[00001, 00001, 00000]"), SV("{::05o}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBdosxX"))
+    check_exception("The format-spec type has a type not supported for a bool argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^[:::true, :::true, ::false]^^^"), SV("{:^^32::>7}"), input);
+  check(SV("^^[:::true, :::true, ::false]^^^"), SV("{:^^{}::>7}"), input, 32);
+  check(SV("^^[:::true, :::true, ::false]^^^"), SV("{:^^{}::>{}}"), input, 32, 7);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 32);
+}
+
+#endif // TEST_STD_CONTAINERS_SEQUENCES_VECTOR_BOOL_VECTOR_BOOL_FMT_FORMAT_FUNCTIONS_TESTS_H

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.vformat.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.vformat.pass.cpp
new file mode 100644
index 000000000000..9e6db80cf989
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.vformat.pass.cpp
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// This test requires the dylib support introduced in D92214.
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}
+
+// <vector>
+
+// template<class T, class charT>
+//   requires is-vector-bool-reference<T>
+// struct formatter<T, charT>
+
+// string vformat(string_view fmt, format_args args);
+// wstring vformat(wstring_view fmt, wformat_args args);
+
+#include <format>
+#include <cassert>
+
+#include "format.functions.tests.h"
+#include "test_macros.h"
+#include "assert_macros.h"
+
+auto test = []<class CharT, class... Args>(
+                std::basic_string_view<CharT> expected, std::basic_string_view<CharT> fmt, Args&&... args) {
+  std::basic_string<CharT> out = std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...));
+  TEST_REQUIRE(
+      out == expected,
+      test_concat_message("\nFormat string   ", fmt, "\nExpected output ", expected, "\nActual output   ", out, '\n'));
+};
+
+auto test_exception =
+    []<class CharT, class... Args>(
+        [[maybe_unused]] std::string_view what,
+        [[maybe_unused]] std::basic_string_view<CharT> fmt,
+        [[maybe_unused]] Args&&... args) {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+      try {
+        TEST_IGNORE_NODISCARD std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...));
+        TEST_FAIL(test_concat_message("\nFormat string   ", fmt, "\nDidn't throw an exception.\n"));
+      } catch (const std::format_error& e) {
+        TEST_LIBCPP_REQUIRE(
+            e.what() == what,
+            test_concat_message(
+                "\nFormat string   ", fmt, "\nExpected exception ", what, "\nActual exception   ", e.what(), '\n'));
+
+        return;
+      }
+      assert(false);
+#endif
+    };
+
+int main(int, char**) {
+  format_tests<char>(test, test_exception);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  format_tests<wchar_t>(test, test_exception);
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.pass.cpp
new file mode 100644
index 000000000000..bb29081dfb89
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.pass.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// This test requires the dylib support introduced in D92214.
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}
+
+// <vector>
+
+// template<class T, class charT>
+//   requires is-vector-bool-reference<T>
+// struct formatter<T, charT>
+
+// template<class FormatContext>
+//   typename FormatContext::iterator
+//     format(const T& r, FormatContext& ctx) const;
+
+// Note this tests the basics of this function. It's tested in more detail in
+// the format functions test.
+
+#include <cassert>
+#include <concepts>
+#include <format>
+#include <vector>
+
+#include "test_format_context.h"
+#include "test_macros.h"
+#include "make_string.h"
+
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
+template <class StringViewT>
+void test_format(StringViewT expected, std::vector<bool>::reference arg) {
+  using CharT      = typename StringViewT::value_type;
+  using String     = std::basic_string<CharT>;
+  using OutIt      = std::back_insert_iterator<String>;
+  using FormatCtxT = std::basic_format_context<OutIt, CharT>;
+
+  const std::formatter<std::vector<bool>::reference, CharT> formatter;
+
+  String result;
+  OutIt out             = std::back_inserter(result);
+  FormatCtxT format_ctx = test_format_context_create<OutIt, CharT>(out, std::make_format_args<FormatCtxT>(arg));
+  formatter.format(arg, format_ctx);
+  assert(result == expected);
+}
+
+template <class CharT>
+void test_fmt() {
+  test_format(SV("true"), std::vector<bool>{true}[0]);
+  test_format(SV("false"), std::vector<bool>{false}[0]);
+}
+
+void test() {
+  test_fmt<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_fmt<wchar_t>();
+#endif
+}
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp
new file mode 100644
index 000000000000..c711e25d1cd0
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// This test requires the dylib support introduced in D92214.
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}
+
+// <vector>
+
+// template<class T, class charT>
+//   requires is-vector-bool-reference<T>
+// struct formatter<T, charT>
+
+// template<class ParseContext>
+//   constexpr typename ParseContext::iterator
+//     parse(ParseContext& ctx);
+
+// Note this tests the basics of this function. It's tested in more detail in
+// the format functions test.
+
+#include <cassert>
+#include <concepts>
+#include <format>
+#include <vector>
+
+#include "test_format_context.h"
+#include "test_macros.h"
+#include "make_string.h"
+
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
+template <class StringViewT>
+constexpr void test_parse(StringViewT fmt) {
+  using CharT    = typename StringViewT::value_type;
+  auto parse_ctx = std::basic_format_parse_context<CharT>(fmt);
+  std::formatter<std::vector<bool, std::allocator<bool>>::reference, CharT> formatter;
+  static_assert(std::semiregular<decltype(formatter)>);
+
+  std::same_as<typename StringViewT::iterator> auto it = formatter.parse(parse_ctx);
+  assert(it == fmt.end() - (!fmt.empty() && fmt.back() == '}'));
+}
+
+template <class CharT>
+constexpr void test_fmt() {
+  test_parse(SV(""));
+  test_parse(SV("b"));
+
+  test_parse(SV("}"));
+  test_parse(SV("b}"));
+}
+
+constexpr bool test() {
+  test_fmt<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_fmt<wchar_t>();
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
index 06a29502a972..cef22792f3aa 100644
--- a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
@@ -38,6 +38,7 @@
 #include <variant>
 
 #include "test_macros.h"
+#include "min_allocator.h"
 
 #ifndef TEST_HAS_NO_FILESYSTEM_LIBRARY
 #  include <filesystem>
@@ -194,6 +195,12 @@ void test_P1636() {
   assert_is_not_formattable<std::unique_ptr<int>, CharT>();
 }
 
+template <class CharT, class Vector>
+void test_P2286_vector_bool() {
+  assert_is_formattable<Vector, CharT>();
+  assert_is_formattable<typename Vector::reference, CharT>();
+}
+
 // Tests for P2286 Formatting ranges
 template <class CharT>
 void test_P2286() {
@@ -223,6 +230,10 @@ void test_P2286() {
 
   assert_is_formattable<std::pair<int, int>, CharT>();
   assert_is_formattable<std::tuple<int>, CharT>();
+
+  test_P2286_vector_bool<CharT, std::vector<bool>>();
+  test_P2286_vector_bool<CharT, std::vector<bool, std::allocator<bool>>>();
+  test_P2286_vector_bool<CharT, std::vector<bool, min_allocator<bool>>>();
 }
 
 class c {


        


More information about the libcxx-commits mailing list