Skip to content

Conversation

kazutakahirata
Copy link
Contributor

Currently, our llvm::identity is not quite like std::identity from
C++20. Ours is a template struct while std::identity is a
non-template struct with templatized operator(). This difference
means that we cannot mechanically replace llvm::identity with
std::identity when we switch to C++20 in the future.

This patch implements llvm::identity_cxx20, which behaves exactly like
std::identity.

Once this patch lands, I'm planning to migrate users of llvm::identity
to the new style. There aren't that many:

  • 4 instances of SparseSet<...>
  • 3 instances of SparseMultiSet<...>
  • about 50 instances of IndexedMap<...>
Currently, our llvm::identity<T> is not quite like std::identity from C++20. Ours is a template struct while std::identity is a non-template struct with templatized operator(). This difference means that we cannot mechanically replace llvm::identity with std::identity when we switch to C++20 in the future. This patch implements llvm::identity_cxx20, which behaves exactly like std::identity. Once this patch lands, I'm planning to migrate users of llvm::identity to the new style. There aren't that many: - 4 instances of SparseSet<...> - 3 instances of SparseMultiSet<...> - about 50 instances of IndexedMap<...>
@llvmbot
Copy link
Member

llvmbot commented Oct 19, 2025

@llvm/pr-subscribers-llvm-adt

Author: Kazu Hirata (kazutakahirata)

Changes

Currently, our llvm::identity<T> is not quite like std::identity from
C++20. Ours is a template struct while std::identity is a
non-template struct with templatized operator(). This difference
means that we cannot mechanically replace llvm::identity with
std::identity when we switch to C++20 in the future.

This patch implements llvm::identity_cxx20, which behaves exactly like
std::identity.

Once this patch lands, I'm planning to migrate users of llvm::identity
to the new style. There aren't that many:

  • 4 instances of SparseSet<...>
  • 3 instances of SparseMultiSet<...>
  • about 50 instances of IndexedMap<...>

Full diff: https://github.com/llvm/llvm-project/pull/164143.diff

2 Files Affected:

  • (modified) llvm/include/llvm/ADT/STLForwardCompat.h (+10)
  • (modified) llvm/unittests/ADT/STLForwardCompatTest.cpp (+22)
diff --git a/llvm/include/llvm/ADT/STLForwardCompat.h b/llvm/include/llvm/ADT/STLForwardCompat.h index 273a5cf8aa8ff..0e9bd2d455965 100644 --- a/llvm/include/llvm/ADT/STLForwardCompat.h +++ b/llvm/include/llvm/ADT/STLForwardCompat.h @@ -19,6 +19,7 @@ #include <optional> #include <type_traits> +#include <utility> namespace llvm { @@ -117,6 +118,15 @@ struct detector<std::void_t<Op<Args...>>, Op, Args...> { template <template <class...> class Op, class... Args> using is_detected = typename detail::detector<void, Op, Args...>::value_t; +struct identity_cxx20 // NOLINT(readability-identifier-naming) +{ + using is_transparent = void; + + template <typename T> constexpr T &&operator()(T &&self) const noexcept { + return std::forward<T>(self); + } +}; + //===----------------------------------------------------------------------===// // Features from C++23 //===----------------------------------------------------------------------===// diff --git a/llvm/unittests/ADT/STLForwardCompatTest.cpp b/llvm/unittests/ADT/STLForwardCompatTest.cpp index 4a8f53cf72f94..2a97e8d6a552f 100644 --- a/llvm/unittests/ADT/STLForwardCompatTest.cpp +++ b/llvm/unittests/ADT/STLForwardCompatTest.cpp @@ -184,4 +184,26 @@ TEST(TransformTest, ToUnderlying) { static_assert(llvm::to_underlying(E3::B3) == 0); } +TEST(STLForwardCompatTest, IdentityCxx20) { + llvm::identity_cxx20 identity; + + // Test with an lvalue. + int X = 42; + int &Y = identity(X); + EXPECT_EQ(&X, &Y); + + // Test with a const lvalue. + const int CX = 10; + const int &CY = identity(CX); + EXPECT_EQ(&CX, &CY); + + // Test with an rvalue. + EXPECT_EQ(identity(123), 123); + + // Test perfect forwarding. + static_assert(std::is_same_v<int &, decltype(identity(X))>); + static_assert(std::is_same_v<const int &, decltype(identity(CX))>); + static_assert(std::is_same_v<int &&, decltype(identity(int(5)))>); +} + } // namespace 
@kazutakahirata kazutakahirata merged commit 622605e into llvm:main Oct 19, 2025
12 checks passed
@kazutakahirata kazutakahirata deleted the cleanup_20251018_ADT_identity_cxx20 branch October 19, 2025 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3 participants