libstdc++: Optimize std::projected<I, std::identity>

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 <jwakely@redhat.com>
This commit is contained in:
Patrick Palka 2024-08-22 09:24:39 -04:00
parent 620232426b
commit 51761c50f8
2 changed files with 10 additions and 0 deletions

View file

@ -803,6 +803,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using __projected_Proj = _Proj;
};
};
// Optimize the common case of the projection being std::identity.
template<typename _Iter>
struct __projected<_Iter, identity>
{ using __type = _Iter; };
} // namespace __detail
/// [projected], projected

View file

@ -22,7 +22,12 @@
template<typename T>
using PI = std::projected<T, std::identity>;
#if __GLIBCXX__
// Verify our projected<I, identity> optimization.
static_assert(std::same_as<PI<int*>, int*>);
#else
static_assert(std::same_as<PI<int*>::value_type, int>);
#endif
static_assert(std::same_as<decltype(*std::declval<const PI<int*>&>()), int&>);
struct X