Skip to content

Commit 622605e

Browse files
[ADT] Add C++20-style llvm::identity_cxx20 (#164143)
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<...>
1 parent 5805e4d commit 622605e

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

llvm/include/llvm/ADT/STLForwardCompat.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <optional>
2121
#include <type_traits>
22+
#include <utility>
2223

2324
namespace llvm {
2425

@@ -117,6 +118,15 @@ struct detector<std::void_t<Op<Args...>>, Op, Args...> {
117118
template <template <class...> class Op, class... Args>
118119
using is_detected = typename detail::detector<void, Op, Args...>::value_t;
119120

121+
struct identity_cxx20 // NOLINT(readability-identifier-naming)
122+
{
123+
using is_transparent = void;
124+
125+
template <typename T> constexpr T &&operator()(T &&self) const noexcept {
126+
return std::forward<T>(self);
127+
}
128+
};
129+
120130
//===----------------------------------------------------------------------===//
121131
// Features from C++23
122132
//===----------------------------------------------------------------------===//

llvm/unittests/ADT/STLForwardCompatTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,26 @@ TEST(TransformTest, ToUnderlying) {
184184
static_assert(llvm::to_underlying(E3::B3) == 0);
185185
}
186186

187+
TEST(STLForwardCompatTest, IdentityCxx20) {
188+
llvm::identity_cxx20 identity;
189+
190+
// Test with an lvalue.
191+
int X = 42;
192+
int &Y = identity(X);
193+
EXPECT_EQ(&X, &Y);
194+
195+
// Test with a const lvalue.
196+
const int CX = 10;
197+
const int &CY = identity(CX);
198+
EXPECT_EQ(&CX, &CY);
199+
200+
// Test with an rvalue.
201+
EXPECT_EQ(identity(123), 123);
202+
203+
// Test perfect forwarding.
204+
static_assert(std::is_same_v<int &, decltype(identity(X))>);
205+
static_assert(std::is_same_v<const int &, decltype(identity(CX))>);
206+
static_assert(std::is_same_v<int &&, decltype(identity(int(5)))>);
207+
}
208+
187209
} // namespace

0 commit comments

Comments
 (0)