diff options
Diffstat (limited to 'include/llvm/ADT/ImmutableList.h')
| -rw-r--r-- | include/llvm/ADT/ImmutableList.h | 36 |
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()); } }; |
