11
11
#define _LIBCPP___FORMAT_FORMAT_FUNCTIONS
12
12
13
13
#include < __algorithm/clamp.h>
14
+ #include < __algorithm/ranges_find_first_of.h>
15
+ #include < __chrono/statically_widen.h>
14
16
#include < __concepts/convertible_to.h>
15
17
#include < __concepts/same_as.h>
16
18
#include < __config>
@@ -448,13 +450,44 @@ format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) {
448
450
}
449
451
# endif
450
452
453
+ template <class _CharT >
454
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<basic_string<_CharT>> __try_constant_folding (
455
+ basic_string_view<_CharT> __fmt,
456
+ basic_format_args<basic_format_context<back_insert_iterator<__format::__output_buffer<_CharT>>, _CharT>> __args) {
457
+ return nullopt;
458
+ if (bool __is_identity = std::ranges::find_first_of (__fmt, array{' {' , ' }' }) == __fmt.end ();
459
+ __builtin_constant_p (__is_identity) && __is_identity)
460
+ return basic_string<_CharT>{__fmt};
461
+
462
+ if (auto __only_first_arg = __fmt == _LIBCPP_STATICALLY_WIDEN (_CharT, " {}" );
463
+ __builtin_constant_p (__only_first_arg) && __only_first_arg) {
464
+ if (auto __arg = __args.get (0 ); __builtin_constant_p (__arg.__type_ )) {
465
+ return std::__visit_format_arg (
466
+ []<class _Tp >(_Tp&& __argument) -> optional<basic_string<_CharT>> {
467
+ if constexpr (is_same_v<remove_cvref_t <_Tp>, basic_string_view<_CharT>>) {
468
+ return basic_string<_CharT>{__argument};
469
+ } else {
470
+ return nullopt;
471
+ }
472
+ },
473
+ __arg);
474
+ }
475
+ }
476
+
477
+ return nullopt;
478
+ }
479
+
451
480
// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
452
481
// fires too eagerly, see http://llvm.org/PR61563.
453
482
template <class = void >
454
483
[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat (string_view __fmt, format_args __args) {
455
- string __res;
456
- std::vformat_to (std::back_inserter (__res), __fmt, __args);
457
- return __res;
484
+ return std::__try_constant_folding (__fmt, __args)
485
+ .or_else ([&]() -> optional<string> {
486
+ string __res;
487
+ std::vformat_to (std::back_inserter (__res), __fmt, __args);
488
+ return __res;
489
+ })
490
+ .value ();
458
491
}
459
492
460
493
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
@@ -463,9 +496,13 @@ template <class = void>
463
496
template <class = void >
464
497
[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
465
498
vformat (wstring_view __fmt, wformat_args __args) {
466
- wstring __res;
467
- std::vformat_to (std::back_inserter (__res), __fmt, __args);
468
- return __res;
499
+ return std::__try_constant_folding (__fmt, __args)
500
+ .or_else ([&]() -> optional<wstring> {
501
+ wstring __res;
502
+ std::vformat_to (std::back_inserter (__res), __fmt, __args);
503
+ return __res;
504
+ })
505
+ .value ();
469
506
}
470
507
# endif
471
508
0 commit comments