1111#define _LIBCPP___FORMAT_FORMAT_FUNCTIONS
1212
1313#include < __algorithm/clamp.h>
14+ #include < __algorithm/ranges_find_first_of.h>
1415#include < __concepts/convertible_to.h>
1516#include < __concepts/same_as.h>
1617#include < __config>
@@ -448,13 +449,44 @@ format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) {
448449}
449450# endif
450451
452+ template <class _CharT >
453+ [[nodiscard]] optional<basic_string<_CharT>> __try_constant_folding (
454+ basic_string_view<_CharT> __fmt,
455+ basic_format_args<basic_format_context<back_insert_iterator<__format::__output_buffer<_CharT>>, _CharT>> __args) {
456+ return nullopt ;
457+ if (bool __is_identity = std::ranges::find_first_of (__fmt, array{' {' , ' }' }) == __fmt.end ();
458+ __builtin_constant_p (__is_identity) && __is_identity)
459+ return basic_string<_CharT>{__fmt};
460+
461+ if (auto __only_first_arg = __fmt == _LIBCPP_STATICALLY_WIDEN (_CharT, " {}" );
462+ __builtin_constant_p (__only_first_arg) && __only_first_arg) {
463+ if (auto __arg = __args.get (0 ); __builtin_constant_p (__arg.__type_ )) {
464+ return std::__visit_format_arg (
465+ []<class _Tp >(_Tp&& __argument) -> optional<basic_string<_CharT>> {
466+ if constexpr (is_same_v<remove_cvref_t <_Tp>, basic_string_view<_CharT>>) {
467+ return basic_string<_CharT>{__argument};
468+ } else {
469+ return nullopt ;
470+ }
471+ },
472+ __arg);
473+ }
474+ }
475+
476+ return nullopt ;
477+ }
478+
451479// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
452480// fires too eagerly, see http://llvm.org/PR61563.
453481template <class = void >
454482[[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;
483+ return std::__try_constant_folding (__fmt, __args)
484+ .or_else ([&]() -> optional<string> {
485+ string __res;
486+ std::vformat_to (std::back_inserter (__res), __fmt, __args);
487+ return __res;
488+ })
489+ .value ();
458490}
459491
460492# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
@@ -463,9 +495,13 @@ template <class = void>
463495template <class = void >
464496[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
465497vformat (wstring_view __fmt, wformat_args __args) {
466- wstring __res;
467- std::vformat_to (std::back_inserter (__res), __fmt, __args);
468- return __res;
498+ return std::__try_constant_folding (__fmt, __args)
499+ .or_else ([&]() -> optional<wstring> {
500+ wstring __res;
501+ std::vformat_to (std::back_inserter (__res), __fmt, __args);
502+ return __res;
503+ })
504+ .value ();
469505}
470506# endif
471507
0 commit comments