[libcxx-commits] [libcxx] f08df56 - [libc++][format] Implements P3107R5 in <format>. (#86713)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jul 30 10:04:29 PDT 2024
Author: Mark de Wever
Date: 2024-07-30T19:04:26+02:00
New Revision: f08df56d3af3e67ab39ebbfb62be3ed3f86d0c9d
URL: https://github.com/llvm/llvm-project/commit/f08df56d3af3e67ab39ebbfb62be3ed3f86d0c9d
DIFF: https://github.com/llvm/llvm-project/commit/f08df56d3af3e67ab39ebbfb62be3ed3f86d0c9d.diff
LOG: [libc++][format] Implements P3107R5 in <format>. (#86713)
This adds the new std::enable_nonlocking_formatter_optimization trait in
<format>. This trait will be used in std::print to implement the
performance benefits.
Implements parts of
- P3107R5 - Permit an efficient implementation of ``std::print``
Added:
libcxx/test/std/utilities/format/format.formatter/format.formatter.locking/enable_nonlocking_formatter_optimization.compile.pass.cpp
Modified:
libcxx/include/__format/formatter.h
libcxx/include/__format/formatter_bool.h
libcxx/include/__format/formatter_char.h
libcxx/include/__format/formatter_floating_point.h
libcxx/include/__format/formatter_integer.h
libcxx/include/__format/formatter_pointer.h
libcxx/include/__format/formatter_string.h
libcxx/include/format
libcxx/modules/std/format.inc
Removed:
################################################################################
diff --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h
index e2f418f936ee1..39c2670dd8431 100644
--- a/libcxx/include/__format/formatter.h
+++ b/libcxx/include/__format/formatter.h
@@ -39,6 +39,9 @@ struct _LIBCPP_TEMPLATE_VIS formatter {
# if _LIBCPP_STD_VER >= 23
+template <class _Tp>
+constexpr bool enable_nonlocking_formatter_optimization = false;
+
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr void __set_debug_format(_Tp& __formatter) {
if constexpr (requires { __formatter.set_debug_format(); })
diff --git a/libcxx/include/__format/formatter_bool.h b/libcxx/include/__format/formatter_bool.h
index 17dc69541e8fe..63aa815efbe9b 100644
--- a/libcxx/include/__format/formatter_bool.h
+++ b/libcxx/include/__format/formatter_bool.h
@@ -69,7 +69,11 @@ struct _LIBCPP_TEMPLATE_VIS formatter<bool, _CharT> {
__format_spec::__parser<_CharT> __parser_;
};
-#endif //_LIBCPP_STD_VER >= 20
+# if _LIBCPP_STD_VER >= 23
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<bool> = true;
+# endif //_LIBCPP_STD_VER >= 23
+#endif //_LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__format/formatter_char.h b/libcxx/include/__format/formatter_char.h
index d33e84368a765..abfd65a428298 100644
--- a/libcxx/include/__format/formatter_char.h
+++ b/libcxx/include/__format/formatter_char.h
@@ -83,9 +83,17 @@ struct _LIBCPP_TEMPLATE_VIS formatter<char, wchar_t> : public __formatter_char<w
template <>
struct _LIBCPP_TEMPLATE_VIS formatter<wchar_t, wchar_t> : public __formatter_char<wchar_t> {};
-
# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
+# if _LIBCPP_STD_VER >= 23
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<char> = true;
+# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<wchar_t> = true;
+# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
+# endif //_LIBCPP_STD_VER >= 23
+
#endif //_LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h
index fa42ba203b0b5..334755f4e8143 100644
--- a/libcxx/include/__format/formatter_floating_point.h
+++ b/libcxx/include/__format/formatter_floating_point.h
@@ -774,6 +774,14 @@ struct _LIBCPP_TEMPLATE_VIS formatter<double, _CharT> : public __formatter_float
template <__fmt_char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS formatter<long double, _CharT> : public __formatter_floating_point<_CharT> {};
+# if _LIBCPP_STD_VER >= 23
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<float> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<double> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<long double> = true;
+# endif //_LIBCPP_STD_VER >= 23
#endif //_LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__format/formatter_integer.h b/libcxx/include/__format/formatter_integer.h
index 41400f00478eb..2c2e799505367 100644
--- a/libcxx/include/__format/formatter_integer.h
+++ b/libcxx/include/__format/formatter_integer.h
@@ -88,7 +88,38 @@ template <__fmt_char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS formatter<__uint128_t, _CharT> : public __formatter_integer<_CharT> {};
# endif
-#endif //_LIBCPP_STD_VER >= 20
+# if _LIBCPP_STD_VER >= 23
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<signed char> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<short> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<int> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<long> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<long long> = true;
+# ifndef _LIBCPP_HAS_NO_INT128
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<__int128_t> = true;
+# endif
+
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<unsigned char> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<unsigned short> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<unsigned> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<unsigned long> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<unsigned long long> = true;
+# ifndef _LIBCPP_HAS_NO_INT128
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<__uint128_t> = true;
+# endif
+# endif //_LIBCPP_STD_VER >= 23
+#endif //_LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__format/formatter_pointer.h b/libcxx/include/__format/formatter_pointer.h
index 6941343efd91f..e1c062cec6ed2 100644
--- a/libcxx/include/__format/formatter_pointer.h
+++ b/libcxx/include/__format/formatter_pointer.h
@@ -65,6 +65,14 @@ struct _LIBCPP_TEMPLATE_VIS formatter<void*, _CharT> : public __formatter_pointe
template <__fmt_char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS formatter<const void*, _CharT> : public __formatter_pointer<_CharT> {};
+# if _LIBCPP_STD_VER >= 23
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<nullptr_t> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<void*> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<const void*> = true;
+# endif //_LIBCPP_STD_VER >= 23
#endif //_LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__format/formatter_string.h b/libcxx/include/__format/formatter_string.h
index 347439fc8dff1..dee2b3ad073a5 100644
--- a/libcxx/include/__format/formatter_string.h
+++ b/libcxx/include/__format/formatter_string.h
@@ -143,7 +143,32 @@ struct _LIBCPP_TEMPLATE_VIS formatter<basic_string_view<_CharT, _Traits>, _CharT
}
};
-#endif //_LIBCPP_STD_VER >= 20
+# if _LIBCPP_STD_VER >= 23
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<char*> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<const char*> = true;
+template <size_t _Size>
+inline constexpr bool enable_nonlocking_formatter_optimization<char[_Size]> = true;
+template <class _Traits, class _Allocator>
+inline constexpr bool enable_nonlocking_formatter_optimization<basic_string<char, _Traits, _Allocator>> = true;
+template <class _Traits>
+inline constexpr bool enable_nonlocking_formatter_optimization<basic_string_view<char, _Traits>> = true;
+
+# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<wchar_t*> = true;
+template <>
+inline constexpr bool enable_nonlocking_formatter_optimization<const wchar_t*> = true;
+template <size_t _Size>
+inline constexpr bool enable_nonlocking_formatter_optimization<wchar_t[_Size]> = true;
+template <class _Traits, class _Allocator>
+inline constexpr bool enable_nonlocking_formatter_optimization<basic_string<wchar_t, _Traits, _Allocator>> = true;
+template <class _Traits>
+inline constexpr bool enable_nonlocking_formatter_optimization<basic_string_view<wchar_t, _Traits>> = true;
+# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
+# endif //_LIBCPP_STD_VER >= 23
+#endif //_LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/format b/libcxx/include/format
index a88b3ef8528e2..449e6f0bf3fb6 100644
--- a/libcxx/include/format
+++ b/libcxx/include/format
@@ -126,6 +126,9 @@ namespace std {
// [format.formatter], formatter
template<class T, class charT = char> struct formatter;
+ template<class T>
+ constexpr bool enable_nonlocking_formatter_optimization = false; // since C++23
+
// [format.parse.ctx], class template basic_format_parse_context
template<class charT> class basic_format_parse_context;
using format_parse_context = basic_format_parse_context<char>;
@@ -133,7 +136,7 @@ namespace std {
// [format.range], formatting of ranges
// [format.range.fmtkind], variable template format_kind
- enum class range_format { // since C++23
+ enum class range_format { // since C++23
disabled,
map,
set,
@@ -143,20 +146,20 @@ namespace std {
};
template<class R>
- constexpr unspecified format_kind = unspecified; // since C++23
+ constexpr unspecified format_kind = unspecified; // since C++23
template<ranges::input_range R>
requires same_as<R, remove_cvref_t<R>>
- constexpr range_format format_kind<R> = see below; // since C++23
+ constexpr range_format format_kind<R> = see below; // since C++23
// [format.range.formatter], class template range_formatter
template<class T, class charT = char>
requires same_as<remove_cvref_t<T>, T> && formattable<T, charT>
- class range_formatter; // since C++23
+ class range_formatter; // since C++23
// [format.range.fmtdef], class template range-default-formatter
template<range_format K, ranges::input_range R, class charT>
- struct range-default-formatter; // exposition only, since C++23
+ struct range-default-formatter; // exposition only, since C++23
// [format.range.fmtmap], [format.range.fmtset], [format.range.fmtstr],
// specializations for maps, sets, and strings
@@ -173,7 +176,7 @@ namespace std {
see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); // Deprecated in C++26
// [format.arg.store], class template format-arg-store
- template<class Context, class... Args> struct format-arg-store; // exposition only
+ template<class Context, class... Args> struct format-arg-store; // exposition only
template<class Context = format_context, class... Args>
format-arg-store<Context, Args...>
diff --git a/libcxx/modules/std/format.inc b/libcxx/modules/std/format.inc
index 743a43811005a..09aa03ad73e38 100644
--- a/libcxx/modules/std/format.inc
+++ b/libcxx/modules/std/format.inc
@@ -46,6 +46,8 @@ export namespace std {
using std::formatter;
#if _LIBCPP_STD_VER >= 23
+ using std::enable_nonlocking_formatter_optimization;
+
// [format.formattable], concept formattable
using std::formattable;
#endif
diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.locking/enable_nonlocking_formatter_optimization.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.locking/enable_nonlocking_formatter_optimization.compile.pass.cpp
new file mode 100644
index 0000000000000..fb078fdc7559e
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.locking/enable_nonlocking_formatter_optimization.compile.pass.cpp
@@ -0,0 +1,235 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// template<class T>
+// constexpr bool enable_nonlocking_formatter_optimization = false;
+
+// Remarks: Pursuant to [namespace.std], users may specialize
+// enable_nonlocking_formatter_optimization for cv-unqualified program-defined
+// types. Such specializations shall be usable in constant expressions
+// ([expr.const]) and have type const bool.
+
+// [format.formatter.spec]
+// In addition, for each type T for which a formatter specialization is provided
+// above, each of the headers provides the following specialization:
+//
+// template<>
+// inline constexpr bool enable_nonlocking_formatter_optimization<T> = true;
+
+#include <array>
+#include <bitset>
+#include <bitset>
+#include <chrono>
+#include <complex>
+#include <concepts>
+#include <deque>
+#include <filesystem>
+#include <format>
+#include <forward_list>
+#include <list>
+#include <map>
+#include <memory>
+#include <optional>
+#include <queue>
+#include <set>
+#include <span>
+#include <stack>
+#include <system_error>
+#include <tuple>
+#include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
+#include <valarray>
+#include <variant>
+#include <vector>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+#ifndef TEST_HAS_NO_LOCALIZATION
+# include <regex>
+#endif
+#ifndef TEST_HAS_NO_THREADS
+# include <thread>
+#endif
+
+// Tests for P0645 Text Formatting
+template <class CharT>
+void test_P0645() {
+ static_assert(std::enable_nonlocking_formatter_optimization<CharT>);
+
+ static_assert(std::enable_nonlocking_formatter_optimization<CharT*>);
+ static_assert(std::enable_nonlocking_formatter_optimization<const CharT*>);
+ static_assert(std::enable_nonlocking_formatter_optimization<CharT[42]>);
+
+ static_assert(std::enable_nonlocking_formatter_optimization<std::basic_string<CharT>>);
+ static_assert(std::enable_nonlocking_formatter_optimization<std::basic_string_view<CharT>>);
+
+ static_assert(std::enable_nonlocking_formatter_optimization<bool>);
+
+ static_assert(std::enable_nonlocking_formatter_optimization<signed char>);
+ static_assert(std::enable_nonlocking_formatter_optimization<signed short>);
+ static_assert(std::enable_nonlocking_formatter_optimization<signed int>);
+ static_assert(std::enable_nonlocking_formatter_optimization<signed long>);
+ static_assert(std::enable_nonlocking_formatter_optimization<signed long long>);
+#ifndef TEST_HAS_NO_INT128
+ static_assert(std::enable_nonlocking_formatter_optimization<__int128_t>);
+#endif
+
+ static_assert(std::enable_nonlocking_formatter_optimization<unsigned char>);
+ static_assert(std::enable_nonlocking_formatter_optimization<unsigned short>);
+ static_assert(std::enable_nonlocking_formatter_optimization<unsigned int>);
+ static_assert(std::enable_nonlocking_formatter_optimization<unsigned long>);
+ static_assert(std::enable_nonlocking_formatter_optimization<unsigned long long>);
+#ifndef TEST_HAS_NO_INT128
+ static_assert(std::enable_nonlocking_formatter_optimization<__uint128_t>);
+#endif
+
+ static_assert(std::enable_nonlocking_formatter_optimization<float>);
+ static_assert(std::enable_nonlocking_formatter_optimization<double>);
+ static_assert(std::enable_nonlocking_formatter_optimization<long double>);
+
+ static_assert(std::enable_nonlocking_formatter_optimization<std::nullptr_t>);
+ static_assert(std::enable_nonlocking_formatter_optimization<void*>);
+ static_assert(std::enable_nonlocking_formatter_optimization<const void*>);
+}
+
+// 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.
+void test_P1361() {
+// The chrono formatters require localization support.
+// [time.format]/7
+// If the chrono-specs is omitted, the chrono object is formatted as if by
+// streaming it to std::ostringstream os with the formatting
+// locale imbued and copying os.str() through the output iterator of the
+// context with additional padding and adjustments as specified by the format
+// specifiers.
+// In libc++ std:::ostringstream requires localization support.
+#ifndef TEST_HAS_NO_LOCALIZATION
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::microseconds>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::sys_time<std::chrono::microseconds>>);
+ //static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::utc_time<std::chrono::microseconds>>);
+ //static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::tai_time<std::chrono::microseconds>>);
+ //static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::gps_time<std::chrono::microseconds>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::file_time<std::chrono::microseconds>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::local_time<std::chrono::microseconds>>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::day>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::month>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::year>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::weekday>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::weekday_indexed>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::weekday_last>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::month_day>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::month_day_last>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::month_weekday>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::month_weekday_last>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::year_month>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::year_month_day>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::year_month_day_last>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::year_month_weekday>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::year_month_weekday_last>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::hh_mm_ss<std::chrono::microseconds>>);
+
+ //static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::sys_info>);
+ //static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::local_info>);
+
+ //static_assert(!std::enable_nonlocking_formatter_optimization<std::chrono::zoned_time>);
+
+#endif // TEST_HAS_NO_LOCALIZATION
+}
+
+// Tests for P1636 Formatters for library types
+//
+// The paper hasn't been voted in so currently all formatters are disabled.
+// Note the paper has been abandoned, the types are kept since other papers may
+// introduce these formatters.
+void test_P1636() {
+#ifndef TEST_HAS_NO_THREADS
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::thread::id>);
+#endif
+}
+
+template <class Vector>
+void test_P2286_vector_bool() {
+ static_assert(!std::enable_nonlocking_formatter_optimization<Vector>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<typename Vector::reference>);
+
+ // The const_reference shall be a bool.
+ // However libc++ uses a __bit_const_reference<vector> when
+ // _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL is defined.
+ static_assert(!std::enable_nonlocking_formatter_optimization<const Vector&>);
+ static_assert(std::enable_nonlocking_formatter_optimization<typename Vector::const_reference> ==
+ std::same_as<typename Vector::const_reference, bool>);
+}
+
+// Tests for P2286 Formatting ranges
+void test_P2286() {
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::array<int, 42>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::vector<int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::deque<int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::forward_list<int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::list<int>>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::set<int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::map<int, int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::multiset<int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::multimap<int, int>>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::unordered_set<int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::unordered_map<int, int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::unordered_multiset<int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::unordered_multimap<int, int>>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::stack<int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::queue<int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::priority_queue<int>>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::span<int>>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::valarray<int>>);
+
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::pair<int, int>>);
+ static_assert(!std::enable_nonlocking_formatter_optimization<std::tuple<int>>);
+
+ test_P2286_vector_bool<std::vector<bool>>();
+ test_P2286_vector_bool<std::vector<bool, std::allocator<bool>>>();
+ test_P2286_vector_bool<std::vector<bool, min_allocator<bool>>>();
+}
+
+// The trait does not care about whether the type is formattable, obviously the
+// trait for non formattable types are not used.
+struct not_formattable_nonlocking_disabled {};
+static_assert(!std::enable_nonlocking_formatter_optimization<not_formattable_nonlocking_disabled>);
+
+struct not_formattable_nonlocking_enabled {};
+template <>
+inline constexpr bool std::enable_nonlocking_formatter_optimization<not_formattable_nonlocking_enabled> = true;
+static_assert(std::enable_nonlocking_formatter_optimization<not_formattable_nonlocking_enabled>);
+
+void test() {
+ test_P0645<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ test_P0645<wchar_t>();
+#endif
+ test_P1361();
+ test_P1636();
+ test_P2286();
+}
More information about the libcxx-commits
mailing list