[libcxx-commits] [libcxx] 2b8b48c - [libc++][format] Disable default formatter.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jan 24 09:14:46 PST 2022


Author: Mark de Wever
Date: 2022-01-24T18:14:41+01:00
New Revision: 2b8b48c5a0c40d33569c74924f72cc31055a7b56

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

LOG: [libc++][format] Disable default formatter.

[format.formatter.spec]/5 lists the requirements for the default
formatter. The original implementation didn't implement this. This
implements the default formatter according to the Standard.

This adds additional test to validate the default formatter is disabled
and the required standard formatters are enabled.

While adding the tests it seems the formatters needed a constraint for the
character types they were valid for.

Implements parts of:
- P0645 Text Formatting

Depends on D115988

Reviewed By: ldionne, #libc

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

Added: 
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/types.compile.pass.cpp

Modified: 
    libcxx/include/__format/formatter.h
    libcxx/include/__format/formatter_bool.h
    libcxx/include/__format/formatter_integer.h
    libcxx/include/__format/formatter_string.h

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h
index 0c0c02ba19173..38b73bba32f3e 100644
--- a/libcxx/include/__format/formatter.h
+++ b/libcxx/include/__format/formatter.h
@@ -38,26 +38,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 // to support compilers with partial C++20 support.
 #if !defined(_LIBCPP_HAS_NO_CONCEPTS)
 
-// Currently not implemented specializations throw an exception when used. This
-// does not conform to the Standard. However not all Standard defined formatters
-// have been implemented yet. Until that time the current behavior is intended.
-// TODO FMT Disable the default template.
+/// The default formatter template.
+///
+/// [format.formatter.spec]/5
+/// If F is a disabled specialization of formatter, these values are false:
+/// - is_default_constructible_v<F>,
+/// - is_copy_constructible_v<F>,
+/// - is_move_constructible_v<F>,
+/// - is_copy_assignable<F>, and
+/// - is_move_assignable<F>.
 template <class _Tp, class _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter {
-  _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI auto parse(auto& __parse_ctx)
-      -> decltype(__parse_ctx.begin()) {
-    __throw();
-  }
-
-  _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI auto format(_Tp, auto& __ctx)
-      -> decltype(__ctx.out()) {
-    __throw();
-  }
-
-private:
-  _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw() {
-    __throw_format_error("Argument type not implemented yet");
-  }
+  formatter() = delete;
+  formatter(const formatter&) = delete;
+  formatter& operator=(const formatter&) = delete;
 };
 
 namespace __format_spec {

diff  --git a/libcxx/include/__format/formatter_bool.h b/libcxx/include/__format/formatter_bool.h
index fdd1d75355d24..1e40bc0a435ae 100644
--- a/libcxx/include/__format/formatter_bool.h
+++ b/libcxx/include/__format/formatter_bool.h
@@ -102,7 +102,7 @@ using __formatter_bool = __formatter_integral<__parser_bool<_CharT>>;
 // For each charT, for each cv-unqualified arithmetic type ArithmeticT other
 // than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
 
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<bool, _CharT>
     : public __format_spec::__formatter_bool<_CharT> {
   using _Base = __format_spec::__formatter_bool<_CharT>;

diff  --git a/libcxx/include/__format/formatter_integer.h b/libcxx/include/__format/formatter_integer.h
index 767df36e61eb7..e1f3d4e34897b 100644
--- a/libcxx/include/__format/formatter_integer.h
+++ b/libcxx/include/__format/formatter_integer.h
@@ -81,25 +81,25 @@ using __formatter_integer = __formatter_integral<__parser_integer<_CharT>>;
 // than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
 
 // Signed integral types.
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<signed char, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<short, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<int, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<long long, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
 #ifndef _LIBCPP_HAS_NO_INT128
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<__int128_t, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {
@@ -119,28 +119,28 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
 #endif
 
 // Unsigned integral types.
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<unsigned char, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<unsigned short, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<unsigned, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<unsigned long, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<unsigned long long, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {};
 #ifndef _LIBCPP_HAS_NO_INT128
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<__uint128_t, _CharT>
     : public __format_spec::__formatter_integer<_CharT> {

diff  --git a/libcxx/include/__format/formatter_string.h b/libcxx/include/__format/formatter_string.h
index 75a81f5184a0d..04950faa4a21e 100644
--- a/libcxx/include/__format/formatter_string.h
+++ b/libcxx/include/__format/formatter_string.h
@@ -64,7 +64,7 @@ class _LIBCPP_TEMPLATE_VIS __formatter_string : public __parser_string<_CharT> {
 // [format.formatter.spec]/2.2 For each charT, the string type specializations
 
 // Formatter const char*.
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<const _CharT*, _CharT>
     : public __format_spec::__formatter_string<_CharT> {
@@ -98,7 +98,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
 };
 
 // Formatter char*.
-template <class _CharT>
+template <__formatter::__char_type _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<_CharT*, _CharT> : public formatter<const _CharT*, _CharT> {
   using _Base = formatter<const _CharT*, _CharT>;
@@ -110,7 +110,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
 };
 
 // Formatter const char[].
-template <class _CharT, size_t _Size>
+template <__formatter::__char_type _CharT, size_t _Size>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<const _CharT[_Size], _CharT>
     : public __format_spec::__formatter_string<_CharT> {
@@ -123,7 +123,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
 };
 
 // Formatter std::string.
-template <class _CharT, class _Traits, class _Allocator>
+template <__formatter::__char_type _CharT, class _Traits, class _Allocator>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
     formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT>
     : public __format_spec::__formatter_string<_CharT> {
@@ -138,7 +138,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
 };
 
 // Formatter std::string_view.
-template <class _CharT, class _Traits>
+template <__formatter::__char_type _CharT, class _Traits>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<basic_string_view<_CharT, _Traits>, _CharT>
     : public __format_spec::__formatter_string<_CharT> {
   using _Base = __format_spec::__formatter_string<_CharT>;

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/types.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/types.compile.pass.cpp
new file mode 100644
index 0000000000000..522a583f349cb
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/types.compile.pass.cpp
@@ -0,0 +1,370 @@
+//===----------------------------------------------------------------------===//
+// 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
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// <format>
+
+// template <class _Tp, class _CharT = char>
+// struct formatter;
+
+// Tests the enabled and disabled requirements for std::formatter.
+
+#include <array>
+#include <bitset>
+#include <bitset>
+#include <chrono>
+#include <complex>
+#include <concepts>
+#include <deque>
+#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY
+#  include <filesystem>
+#endif
+#include <format>
+#include <forward_list>
+#include <list>
+#include <memory>
+#include <map>
+#include <optional>
+#include <queue>
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+#  include <regex>
+#endif
+#include <set>
+#include <stack>
+#include <span>
+#ifndef _LIBCPP_HAS_NO_THREADS
+#  include <thread>
+#endif
+#include <tuple>
+#include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
+#include <valarray>
+#include <variant>
+
+#include "test_macros.h"
+
+// Validate default template argument.
+static_assert(std::same_as<std::formatter<int>, std::formatter<int, char>>);
+
+// Concept for an enabled formatter.
+//
+// Since it's not possible to extract the T and CharT types from the formatter
+// they are specified and the proper formatter is always intended to be
+// defaulted.
+//
+// [formatter.requirements]/2
+// A type F meets the Formatter requirements if it meets the BasicFormatter
+// requirements and the expressions shown in Table 71 are valid and have the
+// indicated semantics.
+template <class T, class CharT, class F = std::formatter<T, CharT>>
+concept enabled =
+    // The basic BasicFormatter requirements:
+    std::default_initializable<F> && std::copyable<F> && std::destructible<F> && std::swappable<F> &&
+    // The expressions shown in Table 71
+    requires(F f, std::basic_format_parse_context<CharT> pc, T u, std::basic_format_context<CharT*, CharT> fc) {
+  { f.parse(pc) } -> std::same_as<typename decltype(pc)::iterator>;
+  { f.format(u, fc) } -> std::same_as<typename decltype(fc)::iterator>;
+};
+
+// Concept for a disabled formatter.
+//
+// This uses the same template arguments as enable. This isn't required since
+// the concept doesn't need to inspect T and CharT. This makes it easier for
+// future changes. For example P2286 formatting ranges intents to change
+// std::formatter<std::vector<int>> from disabled to enabled. The current way
+// makes it easy to define a macro like
+// #if TEST_STD_VER > 23
+//   TEST_ENABLED_AFTER_CXX23(T, CharT) enabled<T, CharT>
+// #else
+//   TEST_ENABLED_AFTER_CXX23(T, CharT) disabled<T, CharT>
+// #endif
+template <class T, class CharT, class F = std::formatter<T, CharT>>
+// [formatter.requirements]/5
+// If F is a disabled specialization of formatter, these values are false:
+concept disabled = !std::is_default_constructible_v<F> && !std::is_copy_constructible_v<F> &&
+                   !std::is_move_constructible_v<F> && !std::is_copy_assignable_v<F> && !std::is_move_assignable_v<F>;
+
+template <class T, class CharT>
+void assert_formatter_is_disabled() {
+  static_assert(disabled<T, CharT>);
+}
+
+template <class T, class CharT>
+void assert_formatter_is_enabled() {
+  // Only formatters for CharT == char || CharT == wchar_t are enabled for the
+  // standard formatters. When CharT is a 
diff erent type the formatter should
+  // be disabled.
+  if constexpr (std::same_as<CharT, char>
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+                || std::same_as<CharT, wchar_t>
+#endif
+  )
+    static_assert(enabled<T, CharT>);
+  else
+    assert_formatter_is_disabled<T, CharT>();
+}
+
+// Tests for P0645 Text Formatting
+template <class CharT>
+void test_P0645() {
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  // Tests the special formatter that converts a char to a wchar_t.
+  assert_formatter_is_enabled<char, wchar_t>();
+#endif
+  assert_formatter_is_enabled<CharT, CharT>();
+
+  assert_formatter_is_enabled<CharT*, CharT>();
+  assert_formatter_is_enabled<const CharT*, CharT>();
+  assert_formatter_is_enabled<const CharT[42], CharT>();
+  assert_formatter_is_enabled<std::basic_string<CharT>, CharT>();
+  assert_formatter_is_enabled<std::basic_string_view<CharT>, CharT>();
+
+  assert_formatter_is_enabled<bool, CharT>();
+
+  assert_formatter_is_enabled<signed char, CharT>();
+  assert_formatter_is_enabled<signed short, CharT>();
+  assert_formatter_is_enabled<signed int, CharT>();
+  assert_formatter_is_enabled<signed long, CharT>();
+  assert_formatter_is_enabled<signed long long, CharT>();
+#ifndef _LIBCPP_HAS_NO_INT128
+  assert_formatter_is_enabled<__int128_t, CharT>();
+#endif
+
+  assert_formatter_is_enabled<unsigned char, CharT>();
+  assert_formatter_is_enabled<unsigned short, CharT>();
+  assert_formatter_is_enabled<unsigned int, CharT>();
+  assert_formatter_is_enabled<unsigned long, CharT>();
+  assert_formatter_is_enabled<unsigned long long, CharT>();
+#ifndef _LIBCPP_HAS_NO_INT128
+  assert_formatter_is_enabled<__uint128_t, CharT>();
+#endif
+
+  assert_formatter_is_enabled<float, CharT>();
+  assert_formatter_is_enabled<double, CharT>();
+  assert_formatter_is_enabled<long double, CharT>();
+
+  assert_formatter_is_enabled<std::nullptr_t, CharT>();
+  assert_formatter_is_enabled<void*, CharT>();
+  assert_formatter_is_enabled<const void*, CharT>();
+}
+
+// Tests for P1361 Integration of chrono with text formatting
+//
+// Some tests are commented out since these types haven't been implemented in
+// chrono yet. After P1361 has been implemented these formatters should be all
+// enabled.
+template <class CharT>
+void test_P1361() {
+  assert_formatter_is_disabled<std::chrono::microseconds, CharT>();
+
+  assert_formatter_is_disabled<std::chrono::sys_time<std::chrono::microseconds>, CharT>();
+  //assert_formatter_is_enabled<std::chrono::utc_time<std::chrono::microseconds>, CharT>();
+  //assert_formatter_is_enabled<std::chrono::tai_time<std::chrono::microseconds>, CharT>();
+  //assert_formatter_is_enabled<std::chrono::gps_time<std::chrono::microseconds>, CharT>();
+  assert_formatter_is_disabled<std::chrono::file_time<std::chrono::microseconds>, CharT>();
+  assert_formatter_is_disabled<std::chrono::local_time<std::chrono::microseconds>, CharT>();
+
+  assert_formatter_is_disabled<std::chrono::day, CharT>();
+  assert_formatter_is_disabled<std::chrono::month, CharT>();
+  assert_formatter_is_disabled<std::chrono::year, CharT>();
+
+  assert_formatter_is_disabled<std::chrono::weekday, CharT>();
+  assert_formatter_is_disabled<std::chrono::weekday_indexed, CharT>();
+  assert_formatter_is_disabled<std::chrono::weekday_last, CharT>();
+
+  assert_formatter_is_disabled<std::chrono::month_day, CharT>();
+  assert_formatter_is_disabled<std::chrono::month_day_last, CharT>();
+  assert_formatter_is_disabled<std::chrono::month_weekday, CharT>();
+  assert_formatter_is_disabled<std::chrono::month_weekday_last, CharT>();
+
+  assert_formatter_is_disabled<std::chrono::year_month, CharT>();
+  assert_formatter_is_disabled<std::chrono::year_month_day, CharT>();
+  assert_formatter_is_disabled<std::chrono::year_month_day_last, CharT>();
+  assert_formatter_is_disabled<std::chrono::year_month_weekday, CharT>();
+  assert_formatter_is_disabled<std::chrono::year_month_weekday_last, CharT>();
+
+  assert_formatter_is_disabled<std::chrono::hh_mm_ss<std::chrono::microseconds>, CharT>();
+
+  //assert_formatter_is_enabled<std::chrono::sys_info, CharT>();
+  //assert_formatter_is_enabled<std::chrono::local_info, CharT>();
+
+  //assert_formatter_is_enabled<std::chrono::zoned_time, CharT>();
+}
+
+// Tests for P1636 Formatters for library types
+//
+// The paper hasn't been voted in so currently all formatters are disabled.
+// TODO validate whether the test is correct after the paper has been accepted.
+template <class CharT>
+void test_P1636() {
+  assert_formatter_is_disabled<std::basic_streambuf<CharT>, CharT>();
+  assert_formatter_is_disabled<std::bitset<42>, CharT>();
+  assert_formatter_is_disabled<std::complex<double>, CharT>();
+  assert_formatter_is_disabled<std::error_code, CharT>();
+#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY
+  assert_formatter_is_disabled<std::filesystem::path, CharT>();
+#endif
+  assert_formatter_is_disabled<std::shared_ptr<int>, CharT>();
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+  assert_formatter_is_disabled<std::sub_match<CharT*>, CharT>();
+#endif
+#ifndef _LIBCPP_HAS_NO_THREADS
+  assert_formatter_is_disabled<std::thread::id, CharT>();
+#endif
+  assert_formatter_is_disabled<std::unique_ptr<int>, CharT>();
+}
+
+// Tests for P2286 Formatting ranges
+//
+// The paper hasn't been voted in so currently all formatters are disabled.
+// TODO validate whether the test is correct after the paper has been accepted.
+template <class CharT>
+void test_P2286() {
+  assert_formatter_is_disabled<std::array<int, 42>, CharT>();
+  assert_formatter_is_disabled<std::vector<int>, CharT>();
+  assert_formatter_is_disabled<std::deque<int>, CharT>();
+  assert_formatter_is_disabled<std::forward_list<int>, CharT>();
+  assert_formatter_is_disabled<std::list<int>, CharT>();
+
+  assert_formatter_is_disabled<std::set<int>, CharT>();
+  assert_formatter_is_disabled<std::map<int, int>, CharT>();
+  assert_formatter_is_disabled<std::multiset<int>, CharT>();
+  assert_formatter_is_disabled<std::multimap<int, int>, CharT>();
+
+  assert_formatter_is_disabled<std::unordered_set<int>, CharT>();
+  assert_formatter_is_disabled<std::unordered_map<int, int>, CharT>();
+  assert_formatter_is_disabled<std::unordered_multiset<int>, CharT>();
+  assert_formatter_is_disabled<std::unordered_multimap<int, int>, CharT>();
+
+  assert_formatter_is_disabled<std::stack<int>, CharT>();
+  assert_formatter_is_disabled<std::queue<int>, CharT>();
+  assert_formatter_is_disabled<std::priority_queue<int>, CharT>();
+
+  assert_formatter_is_disabled<std::span<int>, CharT>();
+
+  assert_formatter_is_disabled<std::valarray<int>, CharT>();
+
+  assert_formatter_is_disabled<std::pair<int, int>, CharT>();
+  assert_formatter_is_disabled<std::tuple<int>, CharT>();
+}
+
+class c {
+  void f();
+  void fc() const;
+  static void sf();
+};
+enum e { a };
+enum class ec { a };
+template <class CharT>
+void test_disabled() {
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  assert_formatter_is_disabled<const char*, wchar_t>();
+#endif
+  assert_formatter_is_disabled<const char*, char8_t>();
+  assert_formatter_is_disabled<const char*, char16_t>();
+  assert_formatter_is_disabled<const char*, char32_t>();
+
+  assert_formatter_is_disabled<c, CharT>();
+  assert_formatter_is_disabled<const c, CharT>();
+  assert_formatter_is_disabled<volatile c, CharT>();
+  assert_formatter_is_disabled<const volatile c, CharT>();
+
+  assert_formatter_is_disabled<e, CharT>();
+  assert_formatter_is_disabled<const e, CharT>();
+  assert_formatter_is_disabled<volatile e, CharT>();
+  assert_formatter_is_disabled<const volatile e, CharT>();
+
+  assert_formatter_is_disabled<ec, CharT>();
+  assert_formatter_is_disabled<const ec, CharT>();
+  assert_formatter_is_disabled<volatile ec, CharT>();
+  assert_formatter_is_disabled<const volatile ec, CharT>();
+
+  assert_formatter_is_disabled<int*, CharT>();
+  assert_formatter_is_disabled<const int*, CharT>();
+  assert_formatter_is_disabled<volatile int*, CharT>();
+  assert_formatter_is_disabled<const volatile int*, CharT>();
+
+  assert_formatter_is_disabled<c*, CharT>();
+  assert_formatter_is_disabled<const c*, CharT>();
+  assert_formatter_is_disabled<volatile c*, CharT>();
+  assert_formatter_is_disabled<const volatile c*, CharT>();
+
+  assert_formatter_is_disabled<e*, CharT>();
+  assert_formatter_is_disabled<const e*, CharT>();
+  assert_formatter_is_disabled<volatile e*, CharT>();
+  assert_formatter_is_disabled<const volatile e*, CharT>();
+
+  assert_formatter_is_disabled<ec*, CharT>();
+  assert_formatter_is_disabled<const ec*, CharT>();
+  assert_formatter_is_disabled<volatile ec*, CharT>();
+  assert_formatter_is_disabled<const volatile ec*, CharT>();
+
+  assert_formatter_is_disabled<void (*)(), CharT>();
+  assert_formatter_is_disabled<void (c::*)(), CharT>();
+  assert_formatter_is_disabled<void (c::*)() const, CharT>();
+
+  assert_formatter_is_disabled<std::optional<int>, CharT>();
+  assert_formatter_is_disabled<std::variant<int>, CharT>();
+
+  assert_formatter_is_disabled<std::shared_ptr<c>, CharT>();
+  assert_formatter_is_disabled<std::unique_ptr<c>, CharT>();
+
+  assert_formatter_is_disabled<std::array<c, 42>, CharT>();
+  assert_formatter_is_disabled<std::vector<c>, CharT>();
+  assert_formatter_is_disabled<std::deque<c>, CharT>();
+  assert_formatter_is_disabled<std::forward_list<c>, CharT>();
+  assert_formatter_is_disabled<std::list<c>, CharT>();
+
+  assert_formatter_is_disabled<std::set<c>, CharT>();
+  assert_formatter_is_disabled<std::map<c, int>, CharT>();
+  assert_formatter_is_disabled<std::multiset<c>, CharT>();
+  assert_formatter_is_disabled<std::multimap<c, int>, CharT>();
+
+  assert_formatter_is_disabled<std::unordered_set<c>, CharT>();
+  assert_formatter_is_disabled<std::unordered_map<c, int>, CharT>();
+  assert_formatter_is_disabled<std::unordered_multiset<c>, CharT>();
+  assert_formatter_is_disabled<std::unordered_multimap<c, int>, CharT>();
+
+  assert_formatter_is_disabled<std::stack<c>, CharT>();
+  assert_formatter_is_disabled<std::queue<c>, CharT>();
+  assert_formatter_is_disabled<std::priority_queue<c>, CharT>();
+
+  assert_formatter_is_disabled<std::span<c>, CharT>();
+
+  assert_formatter_is_disabled<std::valarray<c>, CharT>();
+
+  assert_formatter_is_disabled<std::pair<c, int>, CharT>();
+  assert_formatter_is_disabled<std::tuple<c>, CharT>();
+
+  assert_formatter_is_disabled<std::optional<c>, CharT>();
+  assert_formatter_is_disabled<std::variant<c>, CharT>();
+}
+
+template <class CharT>
+void test() {
+  test_P0645<CharT>();
+  test_P1361<CharT>();
+  test_P1636<CharT>();
+  test_P2286<CharT>();
+  test_disabled<CharT>();
+}
+
+void test() {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+  test<char8_t>();
+  test<char16_t>();
+  test<char32_t>();
+
+  test<int>();
+}


        


More information about the libcxx-commits mailing list