//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains some templates that are useful if you are working with the // STL at all. // // No library is required when using these functions. // //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_STLEXTRAS_H #define LLVM_ADT_STLEXTRAS_H #include "llvm/Support/Compiler.h" #include // for std::size_t #include // for qsort #include #include #include #include // for std::pair namespace llvm { //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// template struct identity : public std::unary_function { Ty &operator()(Ty &self) const { return self; } const Ty &operator()(const Ty &self) const { return self; } }; template struct less_ptr : public std::binary_function { bool operator()(const Ty* left, const Ty* right) const { return *left < *right; } }; template struct greater_ptr : public std::binary_function { bool operator()(const Ty* left, const Ty* right) const { return *right < *left; } }; // deleter - Very very very simple method that is used to invoke operator // delete on something. It is used like this: // // for_each(V.begin(), B.end(), deleter); // template inline void deleter(T *Ptr) { delete Ptr; } //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// // mapped_iterator - This is a simple iterator adapter that causes a function to // be dereferenced whenever operator* is invoked on the iterator. // template class mapped_iterator { RootIt current; UnaryFunc Fn; public: typedef typename std::iterator_traits::iterator_category iterator_category; typedef typename std::iterator_traits::difference_type difference_type; typedef typename UnaryFunc::result_type value_type; typedef void pointer; //typedef typename UnaryFunc::result_type *pointer; typedef void reference; // Can't modify value returned by fn typedef RootIt iterator_type; typedef mapped_iterator _Self; inline const RootIt &getCurrent() const { return current; } inline const UnaryFunc &getFunc() const { return Fn; } inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) : current(I), Fn(F) {} inline value_type operator*() const { // All this work to do this return Fn(*current); // little change } _Self& operator++() { ++current; return *this; } _Self& operator--() { --current; return *this; } _Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; } _Self operator--(int) { _Self __tmp = *this; --current; return __tmp; } _Self operator+ (difference_type n) const { return _Self(current + n, Fn); } _Self& operator+= (difference_type n) { current += n; return *this; } _Self operator- (difference_type n) const { return _Self(current - n, Fn); } _Self& operator-= (difference_type n) { current -= n; return *this; } reference operator[](difference_type n) const { return *(*this + n); } inline bool operator!=(const _Self &X) const { return !operator==(X); } inline bool operator==(const _Self &X) const { return current == X.current; } inline bool operator< (const _Self &X) const { return current < X.current; } inline difference_type operator-(const _Self &X) const { return current - X.current; } }; template inline mapped_iterator<_Iterator, Func> operator+(typename mapped_iterator<_Iterator, Func>::difference_type N, const mapped_iterator<_Iterator, Func>& X) { return mapped_iterator<_Iterator, Func>(X.getCurrent() - N, X.getFunc()); } // map_iterator - Provide a convenient way to create mapped_iterators, just like // make_pair is useful for creating pairs... // template inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { return mapped_iterator(I, F); } //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// /// \brief Function object to check whether the first component of a std::pair /// compares less than the first component of another std::pair. struct less_first { template bool operator()(const T &lhs, const T &rhs) const { return lhs.first < rhs.first; } }; /// \brief Function object to check whether the second component of a std::pair /// compares less than the second component of another std::pair. struct less_second { template bool operator()(const T &lhs, const T &rhs) const { return lhs.second < rhs.second; } }; //===----------------------------------------------------------------------===// // Extra additions for arrays //===----------------------------------------------------------------------===// /// Find where an array ends (for ending iterators) /// This returns a pointer to the byte immediately /// after the end of an array. template inline T *array_endof(T (&x)[N]) { return x+N; } /// Find the length of an array. template inline size_t array_lengthof(T (&)[N]) { return N; } /// array_pod_sort_comparator - This is helper function for array_pod_sort, /// which just uses operator< on T. template inline int array_pod_sort_comparator(const void *P1, const void *P2) { if (*reinterpret_cast(P1) < *reinterpret_cast(P2)) return -1; if (*reinterpret_cast(P2) < *reinterpret_cast(P1)) return 1; return 0; } /// get_array_pod_sort_comparator - This is an internal helper function used to /// get type deduction of T right. template inline int (*get_array_pod_sort_comparator(const T &)) (const void*, const void*) { return array_pod_sort_comparator; } /// array_pod_sort - This sorts an array with the specified start and end /// extent. This is just like std::sort, except that it calls qsort instead of /// using an inlined template. qsort is slightly slower than std::sort, but /// most sorts are not performance critical in LLVM and std::sort has to be /// template instantiated for each type, leading to significant measured code /// bloat. This function should generally be used instead of std::sort where /// possible. /// /// This function assumes that you have simple POD-like types that can be /// compared with operator< and can be moved with memcpy. If this isn't true, /// you should use std::sort. /// /// NOTE: If qsort_r were portable, we could allow a custom comparator and /// default to std::less. template inline void array_pod_sort(IteratorTy Start, IteratorTy End) { // Don't dereference start iterator of empty sequence. if (Start == End) return; qsort(&*Start, End-Start, sizeof(*Start), get_array_pod_sort_comparator(*Start)); } template inline void array_pod_sort( IteratorTy Start, IteratorTy End, int (*Compare)( const typename std::iterator_traits::value_type *, const typename std::iterator_traits::value_type *)) { // Don't dereference start iterator of empty sequence. if (Start == End) return; qsort(&*Start, End - Start, sizeof(*Start), reinterpret_cast(Compare)); } //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// /// For a container of pointers, deletes the pointers and then clears the /// container. template void DeleteContainerPointers(Container &C) { for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) delete *I; C.clear(); } /// In a container of pairs (usually a map) whose second element is a pointer, /// deletes the second elements and then clears the container. template void DeleteContainerSeconds(Container &C) { for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) delete I->second; C.clear(); } //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// #if LLVM_HAS_VARIADIC_TEMPLATES // Implement make_unique according to N3656. /// \brief Constructs a `new T()` with the given args and returns a /// `unique_ptr` which owns the object. /// /// Example: /// /// auto p = make_unique(); /// auto p = make_unique>(0, 1); template typename std::enable_if::value, std::unique_ptr>::type make_unique(Args &&... args) { return std::unique_ptr(new T(std::forward(args)...)); } /// \brief Constructs a `new T[n]` with the given args and returns a /// `unique_ptr` which owns the object. /// /// \param n size of the new array. /// /// Example: /// /// auto p = make_unique(2); // value-initializes the array with 0's. template typename std::enable_if::value && std::extent::value == 0, std::unique_ptr>::type make_unique(size_t n) { return std::unique_ptr(new typename std::remove_extent::type[n]()); } /// This function isn't used and is only here to provide better compile errors. template typename std::enable_if::value != 0>::type make_unique(Args &&...) LLVM_DELETED_FUNCTION; #else template typename std::enable_if::value, std::unique_ptr>::type make_unique() { return std::unique_ptr(new T()); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1) { return std::unique_ptr(new T(std::forward(arg1))); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1, Arg2 &&arg2) { return std::unique_ptr( new T(std::forward(arg1), std::forward(arg2))); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) { return std::unique_ptr(new T(std::forward(arg1), std::forward(arg2), std::forward(arg3))); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) { return std::unique_ptr( new T(std::forward(arg1), std::forward(arg2), std::forward(arg3), std::forward(arg4))); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) { return std::unique_ptr( new T(std::forward(arg1), std::forward(arg2), std::forward(arg3), std::forward(arg4), std::forward(arg5))); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, Arg6 &&arg6) { return std::unique_ptr( new T(std::forward(arg1), std::forward(arg2), std::forward(arg3), std::forward(arg4), std::forward(arg5), std::forward(arg6))); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, Arg6 &&arg6, Arg7 &&arg7) { return std::unique_ptr( new T(std::forward(arg1), std::forward(arg2), std::forward(arg3), std::forward(arg4), std::forward(arg5), std::forward(arg6), std::forward(arg7))); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) { return std::unique_ptr( new T(std::forward(arg1), std::forward(arg2), std::forward(arg3), std::forward(arg4), std::forward(arg5), std::forward(arg6), std::forward(arg7), std::forward(arg8))); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9) { return std::unique_ptr( new T(std::forward(arg1), std::forward(arg2), std::forward(arg3), std::forward(arg4), std::forward(arg5), std::forward(arg6), std::forward(arg7), std::forward(arg8), std::forward(arg9))); } template typename std::enable_if::value, std::unique_ptr>::type make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9, Arg10 &&arg10) { return std::unique_ptr( new T(std::forward(arg1), std::forward(arg2), std::forward(arg3), std::forward(arg4), std::forward(arg5), std::forward(arg6), std::forward(arg7), std::forward(arg8), std::forward(arg9), std::forward(arg10))); } template typename std::enable_if::value &&std::extent::value == 0, std::unique_ptr>::type make_unique(size_t n) { return std::unique_ptr(new typename std::remove_extent::type[n]()); } #endif } // End llvm namespace #endif