summaryrefslogtreecommitdiff
path: root/include/llvm/ADT/ImmutableList.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/ADT/ImmutableList.h')
-rw-r--r--include/llvm/ADT/ImmutableList.h36
1 files changed, 26 insertions, 10 deletions
diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h
index 1f5e9813798d..0541dc2566ed 100644
--- a/include/llvm/ADT/ImmutableList.h
+++ b/include/llvm/ADT/ImmutableList.h
@@ -31,8 +31,9 @@ class ImmutableListImpl : public FoldingSetNode {
T Head;
const ImmutableListImpl* Tail;
- ImmutableListImpl(const T& head, const ImmutableListImpl* tail = nullptr)
- : Head(head), Tail(tail) {}
+ template <typename ElemT>
+ ImmutableListImpl(ElemT &&head, const ImmutableListImpl *tail = nullptr)
+ : Head(std::forward<ElemT>(head)), Tail(tail) {}
public:
ImmutableListImpl(const ImmutableListImpl &) = delete;
@@ -66,6 +67,9 @@ public:
using value_type = T;
using Factory = ImmutableListFactory<T>;
+ static_assert(std::is_trivially_destructible<T>::value,
+ "T must be trivially destructible!");
+
private:
const ImmutableListImpl<T>* X;
@@ -90,6 +94,9 @@ public:
bool operator==(const iterator& I) const { return L == I.L; }
bool operator!=(const iterator& I) const { return L != I.L; }
const value_type& operator*() const { return L->getHead(); }
+ const typename std::remove_reference<value_type>::type* operator->() const {
+ return &L->getHead();
+ }
ImmutableList getList() const { return L; }
};
@@ -123,14 +130,14 @@ public:
bool operator==(const ImmutableList& L) const { return isEqual(L); }
/// getHead - Returns the head of the list.
- const T& getHead() {
+ const T& getHead() const {
assert(!isEmpty() && "Cannot get the head of an empty list.");
return X->getHead();
}
/// getTail - Returns the tail of the list, which is another (possibly empty)
/// ImmutableList.
- ImmutableList getTail() {
+ ImmutableList getTail() const {
return X ? X->getTail() : nullptr;
}
@@ -166,7 +173,8 @@ public:
if (ownsAllocator()) delete &getAllocator();
}
- LLVM_NODISCARD ImmutableList<T> concat(const T &Head, ImmutableList<T> Tail) {
+ template <typename ElemT>
+ LLVM_NODISCARD ImmutableList<T> concat(ElemT &&Head, ImmutableList<T> Tail) {
// Profile the new list to see if it already exists in our cache.
FoldingSetNodeID ID;
void* InsertPos;
@@ -179,7 +187,7 @@ public:
// The list does not exist in our cache. Create it.
BumpPtrAllocator& A = getAllocator();
L = (ListTy*) A.Allocate<ListTy>();
- new (L) ListTy(Head, TailImpl);
+ new (L) ListTy(std::forward<ElemT>(Head), TailImpl);
// Insert the new list into the cache.
Cache.InsertNode(L, InsertPos);
@@ -188,16 +196,24 @@ public:
return L;
}
- LLVM_NODISCARD ImmutableList<T> add(const T& D, ImmutableList<T> L) {
- return concat(D, L);
+ template <typename ElemT>
+ LLVM_NODISCARD ImmutableList<T> add(ElemT &&Data, ImmutableList<T> L) {
+ return concat(std::forward<ElemT>(Data), L);
+ }
+
+ template <typename ...CtorArgs>
+ LLVM_NODISCARD ImmutableList<T> emplace(ImmutableList<T> Tail,
+ CtorArgs &&...Args) {
+ return concat(T(std::forward<CtorArgs>(Args)...), Tail);
}
ImmutableList<T> getEmptyList() const {
return ImmutableList<T>(nullptr);
}
- ImmutableList<T> create(const T& X) {
- return Concat(X, getEmptyList());
+ template <typename ElemT>
+ ImmutableList<T> create(ElemT &&Data) {
+ return concat(std::forward<ElemT>(Data), getEmptyList());
}
};