blob: 06a15734a7b0149963c88b77ba8a29993a99fb0e [file] [log] [blame]
Chris Lattner48486892003-09-30 18:37:50 +00001//===- STLExtras.h - Useful functions when working with the STL -*- C++ -*-===//
John Criswellb2109ce2003-10-20 19:46:57 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Chris Lattner18d64ed2001-06-21 05:25:51 +00009//
10// This file contains some templates that are useful if you are working with the
11// STL at all.
12//
13// No library is required when using these functinons.
14//
15//===----------------------------------------------------------------------===//
16
Brian Gaekea9f6e4a2003-06-17 00:35:55 +000017#ifndef SUPPORT_STLEXTRAS_H
18#define SUPPORT_STLEXTRAS_H
Chris Lattner18d64ed2001-06-21 05:25:51 +000019
20#include <functional>
Chris Lattnerdf6f5832002-10-27 19:16:27 +000021#include "Support/iterator"
Alkis Evlogimenose292da22003-11-05 05:58:26 +000022#include "boost/type_traits/transform_traits.hpp"
Chris Lattner18d64ed2001-06-21 05:25:51 +000023
Brian Gaeked0fde302003-11-11 22:41:34 +000024namespace llvm {
25
Chris Lattner18d64ed2001-06-21 05:25:51 +000026//===----------------------------------------------------------------------===//
Chris Lattner42e018c2001-06-27 23:32:12 +000027// Extra additions to <functional>
28//===----------------------------------------------------------------------===//
29
30// bind_obj - Often times you want to apply the member function of an object
31// as a unary functor. This macro is shorthand that makes it happen less
32// verbosely.
33//
34// Example:
35// struct Summer { void accumulate(int x); }
36// vector<int> Numbers;
37// Summer MyS;
38// for_each(Numbers.begin(), Numbers.end(),
39// bind_obj(&MyS, &Summer::accumulate));
40//
41// TODO: When I get lots of extra time, convert this from an evil macro
42//
43#define bind_obj(OBJ, METHOD) std::bind1st(std::mem_fun(METHOD), OBJ)
44
45
46// bitwise_or - This is a simple functor that applys operator| on its two
47// arguments to get a boolean result.
48//
49template<class Ty>
Chris Lattner697954c2002-01-20 22:54:45 +000050struct bitwise_or : public std::binary_function<Ty, Ty, bool> {
Chris Lattner42e018c2001-06-27 23:32:12 +000051 bool operator()(const Ty& left, const Ty& right) const {
52 return left | right;
53 }
54};
55
56
Chris Lattner577b15f2001-07-02 01:09:41 +000057// deleter - Very very very simple method that is used to invoke operator
58// delete on something. It is used like this:
59//
Chris Lattner87650962002-04-28 16:18:32 +000060// for_each(V.begin(), B.end(), deleter<Interval>);
Chris Lattner577b15f2001-07-02 01:09:41 +000061//
62template <class T>
63static inline void deleter(T *Ptr) {
64 delete Ptr;
65}
66
67
68
Chris Lattner42e018c2001-06-27 23:32:12 +000069//===----------------------------------------------------------------------===//
Chris Lattner18d64ed2001-06-21 05:25:51 +000070// Extra additions to <iterator>
71//===----------------------------------------------------------------------===//
72
73// mapped_iterator - This is a simple iterator adapter that causes a function to
74// be dereferenced whenever operator* is invoked on the iterator.
75//
76// It turns out that this is disturbingly similar to boost::transform_iterator
77//
78#if 1
79template <class RootIt, class UnaryFunc>
80class mapped_iterator {
81 RootIt current;
Chris Lattner643afb32001-09-07 16:30:28 +000082 UnaryFunc Fn;
Chris Lattner18d64ed2001-06-21 05:25:51 +000083public:
Chris Lattner697954c2002-01-20 22:54:45 +000084 typedef typename std::iterator_traits<RootIt>::iterator_category
Chris Lattner18d64ed2001-06-21 05:25:51 +000085 iterator_category;
Chris Lattner697954c2002-01-20 22:54:45 +000086 typedef typename std::iterator_traits<RootIt>::difference_type
Chris Lattner18d64ed2001-06-21 05:25:51 +000087 difference_type;
88 typedef typename UnaryFunc::result_type value_type;
Chris Lattnerd0637252002-10-13 19:30:44 +000089
90 typedef void pointer;
91 //typedef typename UnaryFunc::result_type *pointer;
Chris Lattner18d64ed2001-06-21 05:25:51 +000092 typedef void reference; // Can't modify value returned by fn
93
94 typedef RootIt iterator_type;
95 typedef mapped_iterator<RootIt, UnaryFunc> _Self;
96
97 inline RootIt &getCurrent() const { return current; }
98
Chris Lattner643afb32001-09-07 16:30:28 +000099 inline explicit mapped_iterator(const RootIt &I, UnaryFunc F)
100 : current(I), Fn(F) {}
101 inline mapped_iterator(const mapped_iterator &It)
102 : current(It.current), Fn(It.Fn) {}
Chris Lattner18d64ed2001-06-21 05:25:51 +0000103
104 inline value_type operator*() const { // All this work to do this
Chris Lattner643afb32001-09-07 16:30:28 +0000105 return Fn(*current); // little change
Chris Lattner18d64ed2001-06-21 05:25:51 +0000106 }
107
108 _Self& operator++() { ++current; return *this; }
109 _Self& operator--() { --current; return *this; }
110 _Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; }
111 _Self operator--(int) { _Self __tmp = *this; --current; return __tmp; }
112 _Self operator+ (difference_type n) const { return _Self(current + n); }
113 _Self& operator+= (difference_type n) { current += n; return *this; }
114 _Self operator- (difference_type n) const { return _Self(current - n); }
115 _Self& operator-= (difference_type n) { current -= n; return *this; }
116 reference operator[](difference_type n) const { return *(*this + n); }
117
Chris Lattner697954c2002-01-20 22:54:45 +0000118 inline bool operator!=(const _Self &X) const { return !operator==(X); }
Chris Lattner18d64ed2001-06-21 05:25:51 +0000119 inline bool operator==(const _Self &X) const { return current == X.current; }
120 inline bool operator< (const _Self &X) const { return current < X.current; }
121
122 inline difference_type operator-(const _Self &X) const {
123 return current - X.current;
124 }
125};
126
127template <class _Iterator, class Func>
128inline mapped_iterator<_Iterator, Func>
129operator+(typename mapped_iterator<_Iterator, Func>::difference_type N,
130 const mapped_iterator<_Iterator, Func>& X) {
131 return mapped_iterator<_Iterator, Func>(X.getCurrent() - N);
132}
133
134#else
135
136// This fails to work, because some iterators are not classes, for example
137// vector iterators are commonly value_type **'s
138template <class RootIt, class UnaryFunc>
139class mapped_iterator : public RootIt {
Chris Lattner643afb32001-09-07 16:30:28 +0000140 UnaryFunc Fn;
Chris Lattner18d64ed2001-06-21 05:25:51 +0000141public:
142 typedef typename UnaryFunc::result_type value_type;
143 typedef typename UnaryFunc::result_type *pointer;
144 typedef void reference; // Can't modify value returned by fn
145
146 typedef mapped_iterator<RootIt, UnaryFunc> _Self;
147 typedef RootIt super;
148 inline explicit mapped_iterator(const RootIt &I) : super(I) {}
149 inline mapped_iterator(const super &It) : super(It) {}
150
151 inline value_type operator*() const { // All this work to do
Chris Lattner643afb32001-09-07 16:30:28 +0000152 return Fn(super::operator*()); // this little thing
Chris Lattner18d64ed2001-06-21 05:25:51 +0000153 }
154};
155#endif
156
157// map_iterator - Provide a convenient way to create mapped_iterators, just like
158// make_pair is useful for creating pairs...
159//
160template <class ItTy, class FuncTy>
161inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) {
Chris Lattner643afb32001-09-07 16:30:28 +0000162 return mapped_iterator<ItTy, FuncTy>(I, F);
Chris Lattner18d64ed2001-06-21 05:25:51 +0000163}
164
165
Chris Lattner18d64ed2001-06-21 05:25:51 +0000166//===----------------------------------------------------------------------===//
167// Extra additions to <algorithm>
168//===----------------------------------------------------------------------===//
169
Chris Lattner42e018c2001-06-27 23:32:12 +0000170// apply_until - Apply a functor to a sequence continually, unless the
171// functor returns true. Return true if the functor returned true, return false
172// if the functor never returned true.
173//
174template <class InputIt, class Function>
175bool apply_until(InputIt First, InputIt Last, Function Func) {
176 for ( ; First != Last; ++First)
177 if (Func(*First)) return true;
178 return false;
179}
180
181
Chris Lattner18d64ed2001-06-21 05:25:51 +0000182// reduce - Reduce a sequence values into a single value, given an initial
183// value and an operator.
184//
185template <class InputIt, class Function, class ValueType>
186ValueType reduce(InputIt First, InputIt Last, Function Func, ValueType Value) {
187 for ( ; First != Last; ++First)
188 Value = Func(*First, Value);
189 return Value;
190}
191
192#if 1 // This is likely to be more efficient
193
194// reduce_apply - Reduce the result of applying a function to each value in a
195// sequence, given an initial value, an operator, a function, and a sequence.
196//
197template <class InputIt, class Function, class ValueType, class TransFunc>
Chris Lattner42e018c2001-06-27 23:32:12 +0000198inline ValueType reduce_apply(InputIt First, InputIt Last, Function Func,
199 ValueType Value, TransFunc XForm) {
Chris Lattner18d64ed2001-06-21 05:25:51 +0000200 for ( ; First != Last; ++First)
201 Value = Func(XForm(*First), Value);
202 return Value;
203}
204
205#else // This is arguably more elegant
206
207// reduce_apply - Reduce the result of applying a function to each value in a
208// sequence, given an initial value, an operator, a function, and a sequence.
209//
210template <class InputIt, class Function, class ValueType, class TransFunc>
Chris Lattner42e018c2001-06-27 23:32:12 +0000211inline ValueType reduce_apply2(InputIt First, InputIt Last, Function Func,
212 ValueType Value, TransFunc XForm) {
213 return reduce(map_iterator(First, XForm), map_iterator(Last, XForm),
Chris Lattner18d64ed2001-06-21 05:25:51 +0000214 Func, Value);
215}
216#endif
217
218
Chris Lattner42e018c2001-06-27 23:32:12 +0000219// reduce_apply_bool - Reduce the result of applying a (bool returning) function
220// to each value in a sequence. All of the bools returned by the mapped
221// function are bitwise or'd together, and the result is returned.
Chris Lattner3704c8c2001-06-25 03:54:32 +0000222//
Chris Lattner42e018c2001-06-27 23:32:12 +0000223template <class InputIt, class Function>
224inline bool reduce_apply_bool(InputIt First, InputIt Last, Function Func) {
225 return reduce_apply(First, Last, bitwise_or<bool>(), false, Func);
226}
Chris Lattner18d64ed2001-06-21 05:25:51 +0000227
Chris Lattner643afb32001-09-07 16:30:28 +0000228
229// map - This function maps the specified input sequence into the specified
230// output iterator, applying a unary function in between.
231//
232template <class InIt, class OutIt, class Functor>
233inline OutIt mapto(InIt Begin, InIt End, OutIt Dest, Functor F) {
234 return copy(map_iterator(Begin, F), map_iterator(End, F), Dest);
235}
Alkis Evlogimenose292da22003-11-05 05:58:26 +0000236
237
238//===----------------------------------------------------------------------===//
239// Extra additions to <utility>
240//===----------------------------------------------------------------------===//
241
242// tie - this function ties two objects and returns a temporary object
243// that is assignable from a std::pair. This can be used to make code
244// more readable when using values returned from functions bundled in
245// a std::pair. Since an example is worth 1000 words:
246//
247// typedef std::map<int, int> Int2IntMap;
248//
249// Int2IntMap myMap;
250// Int2IntMap::iterator where;
251// bool inserted;
252// tie(where, inserted) = myMap.insert(std::make_pair(123,456));
253//
254// if (inserted)
255// // do stuff
256// else
257// // do other stuff
258
259namespace
260{
261 template <typename T1, typename T2>
262 struct tier {
263 typedef typename boost::add_reference<T1>::type first_type;
264 typedef typename boost::add_reference<T2>::type second_type;
265
266 first_type first;
267 second_type second;
268
269 tier(first_type f, second_type s) : first(f), second(s) { }
270 tier& operator=(const std::pair<T1, T2>& p) {
271 first = p.first;
272 second = p.second;
273 return *this;
274 }
275 };
276}
277
278template <typename T1, typename T2>
279inline tier<T1, T2> tie(T1& f, T2& s) {
280 return tier<T1, T2>(f, s);
281}
282
Brian Gaeked0fde302003-11-11 22:41:34 +0000283} // End llvm namespace
284
Chris Lattner18d64ed2001-06-21 05:25:51 +0000285#endif