libstdc++: Reorder compile-time checks for __formatter_str::_M_format_range.

Message ID 20260506135456.618822-1-tkaminsk@redhat.com
State New
Headers
Series libstdc++: Reorder compile-time checks for __formatter_str::_M_format_range. |

Commit Message

Tomasz Kaminski May 6, 2026, 1:51 p.m. UTC
  If _M_format_range was called with prvalue of span S (or any contiguous_range),
the previous chain of if-contexpr will call _M_format_range<S&>, then
_M_format_range<const S&> and then format(string_view). By checking for
contiguous_range first call format(string_view) direclty, removing unnecessary
instantiations and symbols.

Similary, for all prvalues of type R, that meet __simply_formattable_range R,
we were instantiating _M_format_range<R&> and then _M_format_range<const R&>.
By moving the if for __simply_formattable_range before is_lvalue_reference_v,
we call _M_format_range<const R&> direclty.

libstdc++-v3/ChangeLog:

	* include/std/format (__formatter_str::_M_format_range):
	Reorder cosntexpr checks, to reduce number of instantiations.
---
Not sure, why I ordered them thay way before. But after re-reading this code
path with my span changes, I realized this order is simply better.

Testing on x86_64-linux. *format* test passed.
OK for trunk when all test passes?

 libstdc++-v3/include/std/format | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
  

Comments

Jonathan Wakely May 11, 2026, 9:19 a.m. UTC | #1
On Wed, 6 May 2026 at 14:55, Tomasz KamiƄski <tkaminsk@redhat.com> wrote:
>
> If _M_format_range was called with prvalue of span S (or any contiguous_range),
> the previous chain of if-contexpr will call _M_format_range<S&>, then
> _M_format_range<const S&> and then format(string_view). By checking for
> contiguous_range first call format(string_view) direclty, removing unnecessary
> instantiations and symbols.
>
> Similary, for all prvalues of type R, that meet __simply_formattable_range R,
> we were instantiating _M_format_range<R&> and then _M_format_range<const R&>.
> By moving the if for __simply_formattable_range before is_lvalue_reference_v,
> we call _M_format_range<const R&> direclty.
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/format (__formatter_str::_M_format_range):
>         Reorder cosntexpr checks, to reduce number of instantiations.
> ---
> Not sure, why I ordered them thay way before. But after re-reading this code
> path with my span changes, I realized this order is simply better.
>
> Testing on x86_64-linux. *format* test passed.
> OK for trunk when all test passes?

OK, thanks

>
>  libstdc++-v3/include/std/format | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
> index 60adca93b5d..0f20fcc8d88 100644
> --- a/libstdc++-v3/include/std/format
> +++ b/libstdc++-v3/include/std/format
> @@ -1438,17 +1438,17 @@ namespace __format
>         {
>           using _Range = remove_reference_t<_Rg>;
>           using _String_view = basic_string_view<_CharT>;
> -         if constexpr (!is_lvalue_reference_v<_Rg>)
> -           return _M_format_range<_Range&>(__rg, __fc);
> -         else if constexpr (!is_const_v<_Range>
> -                              && __simply_formattable_range<_Range, _CharT>)
> -           return _M_format_range<const _Range&>(__rg, __fc);
> -         else if constexpr (ranges::contiguous_range<_Rg>)
> +         if constexpr (ranges::contiguous_range<_Rg>)
>             {
>               _String_view __str(ranges::data(__rg),
>                                  size_t(ranges::distance(__rg)));
>               return format(__str, __fc);
>             }
> +         else if constexpr (!is_const_v<_Range>
> +                               && __simply_formattable_range<_Range, _CharT>)
> +           return _M_format_range<const _Range&>(__rg, __fc);
> +         else if constexpr (!is_lvalue_reference_v<_Rg>)
> +           return _M_format_range<_Range&>(__rg, __fc);
>           else
>             {
>               auto __handle_debug = [this, &__rg]<typename _NOut>(_NOut __nout)
> --
> 2.54.0
>
  

Patch

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 60adca93b5d..0f20fcc8d88 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1438,17 +1438,17 @@  namespace __format
 	{
 	  using _Range = remove_reference_t<_Rg>;
 	  using _String_view = basic_string_view<_CharT>;
-	  if constexpr (!is_lvalue_reference_v<_Rg>)
-	    return _M_format_range<_Range&>(__rg, __fc);
-	  else if constexpr (!is_const_v<_Range>
-			       && __simply_formattable_range<_Range, _CharT>)
-	    return _M_format_range<const _Range&>(__rg, __fc);
-	  else if constexpr (ranges::contiguous_range<_Rg>)
+	  if constexpr (ranges::contiguous_range<_Rg>)
 	    {
 	      _String_view __str(ranges::data(__rg),
 				 size_t(ranges::distance(__rg)));
 	      return format(__str, __fc);
 	    }
+	  else if constexpr (!is_const_v<_Range>
+			        && __simply_formattable_range<_Range, _CharT>)
+	    return _M_format_range<const _Range&>(__rg, __fc);
+	  else if constexpr (!is_lvalue_reference_v<_Rg>)
+	    return _M_format_range<_Range&>(__rg, __fc);
 	  else
 	    {
 	      auto __handle_debug = [this, &__rg]<typename _NOut>(_NOut __nout)