X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FADT%2FSTLExtras.h;h=0605e522d7e775a11e186fcb22056e9ca0fa1f8b;hb=a53ce4e0be51725468c589b1d0a070b30fffacde;hp=5b7b88b90085270c74e1c9a455175a3b3d024d7a;hpb=99ccb1fae75d3d7296c11f1ec4a6eb5e1cbbe4d4;p=oota-llvm.git diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 5b7b88b9008..0605e522d7e 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -18,6 +18,8 @@ #define LLVM_ADT_STLEXTRAS_H #include "llvm/Support/Compiler.h" +#include // for std::all_of +#include #include // for std::size_t #include // for qsort #include @@ -63,123 +65,30 @@ struct greater_ptr : public std::binary_function { /// a function_ref. template class function_ref; -#if LLVM_HAS_VARIADIC_TEMPLATES - template class function_ref { - Ret (*callback)(void *callable, Params ...params); - void *callable; + Ret (*callback)(intptr_t callable, Params ...params); + intptr_t callable; template - static Ret callback_fn(void *callable, Params ...params) { + static Ret callback_fn(intptr_t callable, Params ...params) { return (*reinterpret_cast(callable))( std::forward(params)...); } public: - template - function_ref(Callable &&callable) + template + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} + callable(reinterpret_cast(&callable)) {} Ret operator()(Params ...params) const { return callback(callable, std::forward(params)...); } }; -#else - -template -class function_ref { - Ret (*callback)(void *callable); - void *callable; - - template - static Ret callback_fn(void *callable) { - return (*reinterpret_cast(callable))(); - } - -public: - template - function_ref(Callable &&callable) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()() const { return callback(callable); } -}; - -template -class function_ref { - Ret (*callback)(void *callable, Param1 param1); - void *callable; - - template - static Ret callback_fn(void *callable, Param1 param1) { - return (*reinterpret_cast(callable))( - std::forward(param1)); - } - -public: - template - function_ref(Callable &&callable) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()(Param1 param1) { - return callback(callable, std::forward(param1)); - } -}; - -template -class function_ref { - Ret (*callback)(void *callable, Param1 param1, Param2 param2); - void *callable; - - template - static Ret callback_fn(void *callable, Param1 param1, Param2 param2) { - return (*reinterpret_cast(callable))( - std::forward(param1), - std::forward(param2)); - } - -public: - template - function_ref(Callable &&callable) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()(Param1 param1, Param2 param2) { - return callback(callable, - std::forward(param1), - std::forward(param2)); - } -}; - -template -class function_ref { - Ret (*callback)(void *callable, Param1 param1, Param2 param2, Param3 param3); - void *callable; - - template - static Ret callback_fn(void *callable, Param1 param1, Param2 param2, - Param3 param3) { - return (*reinterpret_cast(callable))( - std::forward(param1), - std::forward(param2), - std::forward(param3)); - } - -public: - template - function_ref(Callable &&callable) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()(Param1 param1, Param2 param2, Param3 param3) { - return callback(callable, - std::forward(param1), - std::forward(param2), - std::forward(param3)); - } -}; - -#endif - // deleter - Very very very simple method that is used to invoke operator // delete on something. It is used like this: // @@ -215,7 +124,6 @@ public: 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; } @@ -227,34 +135,56 @@ public: 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); + mapped_iterator &operator++() { + ++current; + return *this; } - _Self& operator+= (difference_type n) { current += n; return *this; } - _Self operator- (difference_type n) const { - return _Self(current - n, Fn); + mapped_iterator &operator--() { + --current; + return *this; + } + mapped_iterator operator++(int) { + mapped_iterator __tmp = *this; + ++current; + return __tmp; + } + mapped_iterator operator--(int) { + mapped_iterator __tmp = *this; + --current; + return __tmp; + } + mapped_iterator operator+(difference_type n) const { + return mapped_iterator(current + n, Fn); + } + mapped_iterator &operator+=(difference_type n) { + current += n; + return *this; + } + mapped_iterator operator-(difference_type n) const { + return mapped_iterator(current - n, Fn); + } + mapped_iterator &operator-=(difference_type n) { + current -= n; + return *this; } - _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; } + bool operator!=(const mapped_iterator &X) const { return !operator==(X); } + bool operator==(const mapped_iterator &X) const { + return current == X.current; + } + bool operator<(const mapped_iterator &X) const { return current < X.current; } - inline difference_type operator-(const _Self &X) const { + difference_type operator-(const mapped_iterator &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()); +template +inline mapped_iterator +operator+(typename mapped_iterator::difference_type N, + const mapped_iterator &X) { + return mapped_iterator(X.getCurrent() - N, X.getFunc()); } @@ -266,6 +196,30 @@ inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { return mapped_iterator(I, F); } +// Returns an iterator_range over the given container which iterates in reverse. +// Note that the container must have rbegin()/rend() methods for this to work. +template +auto reverse(ContainerTy &C)->decltype(make_range(C.rbegin(), C.rend())) { + return make_range(C.rbegin(), C.rend()); +} + +// Returns a std::reverse_iterator wrapped around the given iterator. +template +std::reverse_iterator make_reverse_iterator(IteratorTy It) { + return std::reverse_iterator(It); +} + +// Returns an iterator_range over the given container which iterates in reverse. +// Note that the container must have begin()/end() methods which return +// bidirectional iterators for this to work. +template +auto reverse(ContainerTy &&C) + ->decltype(make_range(make_reverse_iterator(std::end(C)), + make_reverse_iterator(std::begin(C)))) { + return make_range(make_reverse_iterator(std::end(C)), + make_reverse_iterator(std::begin(C))); +} + //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// @@ -286,6 +240,28 @@ struct less_second { } }; +// A subset of N3658. More stuff can be added as-needed. + +/// \brief Represents a compile-time sequence of integers. +template struct integer_sequence { + typedef T value_type; + + static LLVM_CONSTEXPR size_t size() { return sizeof...(I); } +}; + +/// \brief Alias for the common case of a sequence of size_ts. +template +struct index_sequence : integer_sequence {}; + +template +struct build_index_impl : build_index_impl {}; +template +struct build_index_impl<0, I...> : index_sequence {}; + +/// \brief Creates a compile-time integer sequence for a parameter pack. +template +struct index_sequence_for : build_index_impl {}; + //===----------------------------------------------------------------------===// // Extra additions for arrays //===----------------------------------------------------------------------===// @@ -333,10 +309,11 @@ inline int (*get_array_pod_sort_comparator(const T &)) /// 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)); + // Don't inefficiently call qsort with one element or trigger undefined + // behavior with an empty sequence. + auto NElts = End - Start; + if (NElts <= 1) return; + qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); } template @@ -345,9 +322,11 @@ inline void array_pod_sort( 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), + // Don't inefficiently call qsort with one element or trigger undefined + // behavior with an empty sequence. + auto NElts = End - Start; + if (NElts <= 1) return; + qsort(&*Start, NElts, sizeof(*Start), reinterpret_cast(Compare)); } @@ -373,12 +352,18 @@ void DeleteContainerSeconds(Container &C) { C.clear(); } +/// Provide wrappers to std::all_of which take ranges instead of having to pass +/// being/end explicitly. +template +bool all_of(R &&Range, UnaryPredicate &&P) { + return std::all_of(Range.begin(), Range.end(), + std::forward(P)); +} + //===----------------------------------------------------------------------===// // 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 @@ -412,123 +397,13 @@ make_unique(size_t 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))); -} +make_unique(Args &&...) = delete; -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 +struct FreeDeleter { + void operator()(void* v) { + ::free(v); + } +}; template struct pair_hash { @@ -537,6 +412,35 @@ struct pair_hash { } }; +/// A functor like C++14's std::less in its absence. +struct less { + template bool operator()(A &&a, B &&b) const { + return std::forward(a) < std::forward(b); + } +}; + +/// A functor like C++14's std::equal in its absence. +struct equal { + template bool operator()(A &&a, B &&b) const { + return std::forward(a) == std::forward(b); + } +}; + +/// Binary functor that adapts to any other binary functor after dereferencing +/// operands. +template struct deref { + T func; + // Could be further improved to cope with non-derivable functors and + // non-binary functors (should be a variadic template member function + // operator()). + template + auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { + assert(lhs); + assert(rhs); + return func(*lhs, *rhs); + } +}; + } // End llvm namespace #endif