From 51761c50f843d5be4e24172535e4524b5072f24c Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Thu, 22 Aug 2024 09:24:39 -0400 Subject: [PATCH] libstdc++: Optimize std::projected Algorithms that are generalized to take projections typically default the projection to std::identity, which is equivalent to no projection at all. In that case, I believe we could shortcut the projection logic to return the iterator unchanged rather than wrapping it. This should reduce compile times especially after P2609R3 which made the indirect invocability concepts more expensive to check when actual projections are involved. libstdc++-v3/ChangeLog: * include/bits/iterator_concepts.h (__detail::__projected): Define an optimized partial specialization for when the projection is std::identity. * testsuite/24_iterators/indirect_callable/projected.cc: Verify the optimization. Reviewed-by: Jonathan Wakely --- libstdc++-v3/include/bits/iterator_concepts.h | 5 +++++ .../testsuite/24_iterators/indirect_callable/projected.cc | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index d849ddc32fc..642c709fee0 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -803,6 +803,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __projected_Proj = _Proj; }; }; + + // Optimize the common case of the projection being std::identity. + template + struct __projected<_Iter, identity> + { using __type = _Iter; }; } // namespace __detail /// [projected], projected diff --git a/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc b/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc index 0eec42c2d5f..9ab7db9d65d 100644 --- a/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc +++ b/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc @@ -22,7 +22,12 @@ template using PI = std::projected; +#if __GLIBCXX__ +// Verify our projected optimization. +static_assert(std::same_as, int*>); +#else static_assert(std::same_as::value_type, int>); +#endif static_assert(std::same_as&>()), int&>); struct X