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 that actually behaves like
std::identity. The only difference is that we must refer to it as
llvm::identity<> with <> at the end.

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 that actually behaves like
std::identity.  The only difference is that we must refer to it as
llvm::identity<> with <> at the end.

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 Sep 12, 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 that actually behaves like
std::identity. The only difference is that we must refer to it as
llvm::identity<> with <> at the end.

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/158211.diff

1 Files Affected:

  • (modified) llvm/include/llvm/ADT/identity.h (+17-2)
diff --git a/llvm/include/llvm/ADT/identity.h b/llvm/include/llvm/ADT/identity.h
index 88d033fc01141..9d599c6c192d8 100644
--- a/llvm/include/llvm/ADT/identity.h
+++ b/llvm/include/llvm/ADT/identity.h
@@ -15,10 +15,12 @@
 #ifndef LLVM_ADT_IDENTITY_H
 #define LLVM_ADT_IDENTITY_H
 
+#include <utility>
+
 namespace llvm {
 
-// Similar to `std::identity` from C++20.
-template <class Ty> struct identity {
+// Our legacy llvm::identity, not quite the same as std::identity.
+template <class Ty = void> struct identity {
   using is_transparent = void;
   using argument_type = Ty;
 
@@ -26,6 +28,19 @@ template <class Ty> struct identity {
   const Ty &operator()(const Ty &self) const { return self; }
 };
 
+// Forward-ported from C++20.
+//
+// While we are migrating from the legacy version, we must refer to this
+// template as identity<>.  Once the legacy version is removed, we can
+// make this a non-template struct and remove the <>.
+template <> struct identity<void> {
+  using is_transparent = void;
+
+  template <typename T> constexpr T &&operator()(T &&self) const {
+    return std::forward<T>(self);
+  }
+};
+
 } // namespace llvm
 
 #endif // LLVM_ADT_IDENTITY_H

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants