lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
00001 /*****************************************************/ 00002 /* lean Functional (c) Tobias Zirr 2011 */ 00003 /*****************************************************/ 00004 00005 #ifndef LEAN_FUNCTIONAL_ALGORITHM 00006 #define LEAN_FUNCTIONAL_ALGORITHM 00007 00008 #include "../lean.h" 00009 #include "../tags/noncopyable.h" 00010 #include <functional> 00011 #include <algorithm> 00012 00013 namespace lean 00014 { 00015 namespace functional 00016 { 00017 00019 template <class Iterator1, class Iterator2> 00020 inline bool equal(Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2) 00021 { 00022 Iterator1 it1 = begin1; 00023 Iterator1 it2 = begin2; 00024 00025 bool ended1 = (it1 == end1); 00026 bool ended2 = (it2 == end2); 00027 00028 while (!ended1 && !ended2) 00029 { 00030 if (!(*it1 == *it2)) 00031 return false; 00032 00033 ended1 = (++it1 == end1); 00034 ended2 = (++it2 == end2); 00035 } 00036 00037 return ended1 && ended2; 00038 } 00039 00041 template <class Iterator1, class Iterator2, class Pred> 00042 inline bool equal(Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2, Pred pred) 00043 { 00044 Iterator1 it1 = begin1; 00045 Iterator1 it2 = begin2; 00046 00047 bool ended1 = (it1 == end1); 00048 bool ended2 = (it2 == end2); 00049 00050 while (!ended1 && !ended2) 00051 { 00052 if (!pred(*it1, *it2)) 00053 return false; 00054 00055 ended1 = (++it1 == end1); 00056 ended2 = (++it2 == end2); 00057 } 00058 00059 return ended1 && ended2; 00060 } 00061 00063 template <class Range1, class Range2> 00064 inline bool equal(const Range1 &range1, const Range2 &range2) 00065 { 00066 return equal(range1.begin(), range1.end(), range2.begin(), range2.end()); 00067 } 00068 00070 template <class Range1, class Range2, class Pred> 00071 inline bool equal(const Range1 &range1, const Range2 &range2, Pred pred) 00072 { 00073 return equal(range1.begin(), range1.end(), range2.begin(), range2.end(), pred); 00074 } 00075 00077 template <class Range1, class Range2> 00078 inline bool lexicographical_compare(const Range1 &range1, const Range2 &range2) 00079 { 00080 return std::lexicographical_compare(range1.begin(), range1.end(), range2.begin(), range2.end()); 00081 } 00082 00084 template <class Range1, class Range2, class Pred> 00085 inline bool lexicographical_compare(const Range1 &range1, const Range2 &range2, Pred pred) 00086 { 00087 return std::lexicographical_compare(range1.begin(), range1.end(), range2.begin(), range2.end(), pred); 00088 } 00089 00091 template <class Iterator> 00092 inline Iterator insert_last(Iterator first, Iterator last) 00093 { 00094 for (Iterator current = first; current != last; ++current) 00095 if (*last < *current) 00096 { 00097 std::rotate(current, last, next(last)); 00098 return current; 00099 } 00100 00101 return last; 00102 } 00103 00105 template <class Iterator, class Predicate> 00106 inline Iterator insert_last(Iterator first, Iterator last, Predicate predicate) 00107 { 00108 for (Iterator current = first; current != last; ++current) 00109 if (predicate(*last, *current)) 00110 { 00111 std::rotate(current, last, next(last)); 00112 return current; 00113 } 00114 00115 return last; 00116 } 00117 00118 #ifndef LEAN0X_NO_RVALUE_REFERENCES 00119 00121 template <class Vector, class Value> 00122 inline typename Vector::iterator push_sorted(Vector &vector, Value &&value) 00123 { 00124 vector.push_back( std::forward<Value>(value) ); 00125 return insert_last( vector.begin(), prev(vector.end()) ); 00126 } 00127 00129 template <class Vector, class Value, class Predicate> 00130 inline typename Vector::iterator push_sorted(Vector &vector, Value &&value, Predicate &&predicate) 00131 { 00132 vector.push_back( std::forward<Value>(value) ); 00133 return insert_last( vector.begin(), prev(vector.end()), std::forward<Predicate>(predicate) ); 00134 } 00135 00136 #else 00137 00139 template <class Vector, class Value> 00140 inline typename Vector::iterator push_sorted(Vector &vector, const Value &value) 00141 { 00142 vector.push_back( value ); 00143 return insert_last( vector.begin(), prev(vector.end()) ); 00144 } 00145 00147 template <class Vector, class Value, class Predicate> 00148 inline typename Vector::iterator push_sorted(Vector &vector, const Value &value, Predicate predicate) 00149 { 00150 vector.push_back( value ); 00151 return insert_last( vector.begin(), prev(vector.end()), predicate ); 00152 } 00153 00154 #endif 00155 00157 template <class Iterator, class Value> 00158 inline Iterator find_sorted(Iterator begin, Iterator end, const Value &value) 00159 { 00160 Iterator element = std::lower_bound(begin, end, value); 00161 00162 if (element != end && !(*element == value)) 00163 element = end; 00164 00165 return element; 00166 } 00167 00169 template <class Iterator, class Value, class Ord, class Eq> 00170 inline Iterator find_sorted(Iterator begin, Iterator end, const Value &value, Ord order, Eq equal) 00171 { 00172 Iterator element = std::lower_bound(begin, end, value, order); 00173 00174 if (element != end && !equal(*element, value)) 00175 element = end; 00176 00177 return element; 00178 } 00179 00181 template <class Vector, class Value> 00182 inline bool remove(Vector &vector, const Value &value) 00183 { 00184 bool bRemoved = false; 00185 00186 typename Vector::iterator newEnd = std::remove(vector.begin(), vector.end(), value); 00187 bRemoved = (newEnd != vector.end()); 00188 00189 vector.erase(newEnd, vector.end()); 00190 00191 return bRemoved; 00192 } 00193 00195 template <class Vector, class Value> 00196 inline bool remove_ordered(Vector &vector, const Value &value) 00197 { 00198 bool bRemoved = false; 00199 00200 typename Vector::const_iterator it = vector.begin(); 00201 00202 while (it != vector.end()) 00203 { 00204 if (*it == value) 00205 { 00206 // Not quite optimal, assuming that elements mostly occur only once 00207 it = vector.erase(it); 00208 bRemoved = true; 00209 } 00210 else 00211 ++it; 00212 } 00213 00214 return bRemoved; 00215 } 00216 00217 } // namespace 00218 00219 using functional::equal; 00220 using functional::lexicographical_compare; 00221 using functional::insert_last; 00222 using functional::push_sorted; 00223 using functional::find_sorted; 00224 using functional::remove; 00225 using functional::remove_ordered; 00226 00227 } // namespace 00228 00229 #endif