Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | // STL utility functions. Usually, these replace built-in, but slow(!), |
michael@0 | 6 | // STL functions with more efficient versions. |
michael@0 | 7 | |
michael@0 | 8 | #ifndef BASE_STL_UTIL_INL_H_ |
michael@0 | 9 | #define BASE_STL_UTIL_INL_H_ |
michael@0 | 10 | |
michael@0 | 11 | #include <string.h> // for memcpy |
michael@0 | 12 | #include <functional> |
michael@0 | 13 | #include <set> |
michael@0 | 14 | #include <string> |
michael@0 | 15 | #include <vector> |
michael@0 | 16 | #include <cassert> |
michael@0 | 17 | |
michael@0 | 18 | // Clear internal memory of an STL object. |
michael@0 | 19 | // STL clear()/reserve(0) does not always free internal memory allocated |
michael@0 | 20 | // This function uses swap/destructor to ensure the internal memory is freed. |
michael@0 | 21 | template<class T> void STLClearObject(T* obj) { |
michael@0 | 22 | T tmp; |
michael@0 | 23 | tmp.swap(*obj); |
michael@0 | 24 | obj->reserve(0); // this is because sometimes "T tmp" allocates objects with |
michael@0 | 25 | // memory (arena implementation?). use reserve() |
michael@0 | 26 | // to clear() even if it doesn't always work |
michael@0 | 27 | } |
michael@0 | 28 | |
michael@0 | 29 | // Reduce memory usage on behalf of object if it is using more than |
michael@0 | 30 | // "bytes" bytes of space. By default, we clear objects over 1MB. |
michael@0 | 31 | template <class T> inline void STLClearIfBig(T* obj, size_t limit = 1<<20) { |
michael@0 | 32 | if (obj->capacity() >= limit) { |
michael@0 | 33 | STLClearObject(obj); |
michael@0 | 34 | } else { |
michael@0 | 35 | obj->clear(); |
michael@0 | 36 | } |
michael@0 | 37 | } |
michael@0 | 38 | |
michael@0 | 39 | // Reserve space for STL object. |
michael@0 | 40 | // STL's reserve() will always copy. |
michael@0 | 41 | // This function avoid the copy if we already have capacity |
michael@0 | 42 | template<class T> void STLReserveIfNeeded(T* obj, int new_size) { |
michael@0 | 43 | if (obj->capacity() < new_size) // increase capacity |
michael@0 | 44 | obj->reserve(new_size); |
michael@0 | 45 | else if (obj->size() > new_size) // reduce size |
michael@0 | 46 | obj->resize(new_size); |
michael@0 | 47 | } |
michael@0 | 48 | |
michael@0 | 49 | // STLDeleteContainerPointers() |
michael@0 | 50 | // For a range within a container of pointers, calls delete |
michael@0 | 51 | // (non-array version) on these pointers. |
michael@0 | 52 | // NOTE: for these three functions, we could just implement a DeleteObject |
michael@0 | 53 | // functor and then call for_each() on the range and functor, but this |
michael@0 | 54 | // requires us to pull in all of algorithm.h, which seems expensive. |
michael@0 | 55 | // For hash_[multi]set, it is important that this deletes behind the iterator |
michael@0 | 56 | // because the hash_set may call the hash function on the iterator when it is |
michael@0 | 57 | // advanced, which could result in the hash function trying to deference a |
michael@0 | 58 | // stale pointer. |
michael@0 | 59 | template <class ForwardIterator> |
michael@0 | 60 | void STLDeleteContainerPointers(ForwardIterator begin, |
michael@0 | 61 | ForwardIterator end) { |
michael@0 | 62 | while (begin != end) { |
michael@0 | 63 | ForwardIterator temp = begin; |
michael@0 | 64 | ++begin; |
michael@0 | 65 | delete *temp; |
michael@0 | 66 | } |
michael@0 | 67 | } |
michael@0 | 68 | |
michael@0 | 69 | // STLDeleteContainerPairPointers() |
michael@0 | 70 | // For a range within a container of pairs, calls delete |
michael@0 | 71 | // (non-array version) on BOTH items in the pairs. |
michael@0 | 72 | // NOTE: Like STLDeleteContainerPointers, it is important that this deletes |
michael@0 | 73 | // behind the iterator because if both the key and value are deleted, the |
michael@0 | 74 | // container may call the hash function on the iterator when it is advanced, |
michael@0 | 75 | // which could result in the hash function trying to dereference a stale |
michael@0 | 76 | // pointer. |
michael@0 | 77 | template <class ForwardIterator> |
michael@0 | 78 | void STLDeleteContainerPairPointers(ForwardIterator begin, |
michael@0 | 79 | ForwardIterator end) { |
michael@0 | 80 | while (begin != end) { |
michael@0 | 81 | ForwardIterator temp = begin; |
michael@0 | 82 | ++begin; |
michael@0 | 83 | delete temp->first; |
michael@0 | 84 | delete temp->second; |
michael@0 | 85 | } |
michael@0 | 86 | } |
michael@0 | 87 | |
michael@0 | 88 | // STLDeleteContainerPairFirstPointers() |
michael@0 | 89 | // For a range within a container of pairs, calls delete (non-array version) |
michael@0 | 90 | // on the FIRST item in the pairs. |
michael@0 | 91 | // NOTE: Like STLDeleteContainerPointers, deleting behind the iterator. |
michael@0 | 92 | template <class ForwardIterator> |
michael@0 | 93 | void STLDeleteContainerPairFirstPointers(ForwardIterator begin, |
michael@0 | 94 | ForwardIterator end) { |
michael@0 | 95 | while (begin != end) { |
michael@0 | 96 | ForwardIterator temp = begin; |
michael@0 | 97 | ++begin; |
michael@0 | 98 | delete temp->first; |
michael@0 | 99 | } |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | // STLDeleteContainerPairSecondPointers() |
michael@0 | 103 | // For a range within a container of pairs, calls delete |
michael@0 | 104 | // (non-array version) on the SECOND item in the pairs. |
michael@0 | 105 | template <class ForwardIterator> |
michael@0 | 106 | void STLDeleteContainerPairSecondPointers(ForwardIterator begin, |
michael@0 | 107 | ForwardIterator end) { |
michael@0 | 108 | while (begin != end) { |
michael@0 | 109 | delete begin->second; |
michael@0 | 110 | ++begin; |
michael@0 | 111 | } |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | template<typename T> |
michael@0 | 115 | inline void STLAssignToVector(std::vector<T>* vec, |
michael@0 | 116 | const T* ptr, |
michael@0 | 117 | size_t n) { |
michael@0 | 118 | vec->resize(n); |
michael@0 | 119 | memcpy(&vec->front(), ptr, n*sizeof(T)); |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | /***** Hack to allow faster assignment to a vector *****/ |
michael@0 | 123 | |
michael@0 | 124 | // This routine speeds up an assignment of 32 bytes to a vector from |
michael@0 | 125 | // about 250 cycles per assignment to about 140 cycles. |
michael@0 | 126 | // |
michael@0 | 127 | // Usage: |
michael@0 | 128 | // STLAssignToVectorChar(&vec, ptr, size); |
michael@0 | 129 | // STLAssignToString(&str, ptr, size); |
michael@0 | 130 | |
michael@0 | 131 | inline void STLAssignToVectorChar(std::vector<char>* vec, |
michael@0 | 132 | const char* ptr, |
michael@0 | 133 | size_t n) { |
michael@0 | 134 | STLAssignToVector(vec, ptr, n); |
michael@0 | 135 | } |
michael@0 | 136 | |
michael@0 | 137 | inline void STLAssignToString(std::string* str, const char* ptr, size_t n) { |
michael@0 | 138 | str->resize(n); |
michael@0 | 139 | memcpy(&*str->begin(), ptr, n); |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | // To treat a possibly-empty vector as an array, use these functions. |
michael@0 | 143 | // If you know the array will never be empty, you can use &*v.begin() |
michael@0 | 144 | // directly, but that is allowed to dump core if v is empty. This |
michael@0 | 145 | // function is the most efficient code that will work, taking into |
michael@0 | 146 | // account how our STL is actually implemented. THIS IS NON-PORTABLE |
michael@0 | 147 | // CODE, so call us instead of repeating the nonportable code |
michael@0 | 148 | // everywhere. If our STL implementation changes, we will need to |
michael@0 | 149 | // change this as well. |
michael@0 | 150 | |
michael@0 | 151 | template<typename T> |
michael@0 | 152 | inline T* vector_as_array(std::vector<T>* v) { |
michael@0 | 153 | # ifdef NDEBUG |
michael@0 | 154 | return &*v->begin(); |
michael@0 | 155 | # else |
michael@0 | 156 | return v->empty() ? NULL : &*v->begin(); |
michael@0 | 157 | # endif |
michael@0 | 158 | } |
michael@0 | 159 | |
michael@0 | 160 | template<typename T> |
michael@0 | 161 | inline const T* vector_as_array(const std::vector<T>* v) { |
michael@0 | 162 | # ifdef NDEBUG |
michael@0 | 163 | return &*v->begin(); |
michael@0 | 164 | # else |
michael@0 | 165 | return v->empty() ? NULL : &*v->begin(); |
michael@0 | 166 | # endif |
michael@0 | 167 | } |
michael@0 | 168 | |
michael@0 | 169 | // Return a mutable char* pointing to a string's internal buffer, |
michael@0 | 170 | // which may not be null-terminated. Writing through this pointer will |
michael@0 | 171 | // modify the string. |
michael@0 | 172 | // |
michael@0 | 173 | // string_as_array(&str)[i] is valid for 0 <= i < str.size() until the |
michael@0 | 174 | // next call to a string method that invalidates iterators. |
michael@0 | 175 | // |
michael@0 | 176 | // As of 2006-04, there is no standard-blessed way of getting a |
michael@0 | 177 | // mutable reference to a string's internal buffer. However, issue 530 |
michael@0 | 178 | // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) |
michael@0 | 179 | // proposes this as the method. According to Matt Austern, this should |
michael@0 | 180 | // already work on all current implementations. |
michael@0 | 181 | inline char* string_as_array(std::string* str) { |
michael@0 | 182 | // DO NOT USE const_cast<char*>(str->data())! See the unittest for why. |
michael@0 | 183 | return str->empty() ? NULL : &*str->begin(); |
michael@0 | 184 | } |
michael@0 | 185 | |
michael@0 | 186 | // These are methods that test two hash maps/sets for equality. These exist |
michael@0 | 187 | // because the == operator in the STL can return false when the maps/sets |
michael@0 | 188 | // contain identical elements. This is because it compares the internal hash |
michael@0 | 189 | // tables which may be different if the order of insertions and deletions |
michael@0 | 190 | // differed. |
michael@0 | 191 | |
michael@0 | 192 | template <class HashSet> |
michael@0 | 193 | inline bool |
michael@0 | 194 | HashSetEquality(const HashSet& set_a, |
michael@0 | 195 | const HashSet& set_b) { |
michael@0 | 196 | if (set_a.size() != set_b.size()) return false; |
michael@0 | 197 | for (typename HashSet::const_iterator i = set_a.begin(); |
michael@0 | 198 | i != set_a.end(); |
michael@0 | 199 | ++i) { |
michael@0 | 200 | if (set_b.find(*i) == set_b.end()) |
michael@0 | 201 | return false; |
michael@0 | 202 | } |
michael@0 | 203 | return true; |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | template <class HashMap> |
michael@0 | 207 | inline bool |
michael@0 | 208 | HashMapEquality(const HashMap& map_a, |
michael@0 | 209 | const HashMap& map_b) { |
michael@0 | 210 | if (map_a.size() != map_b.size()) return false; |
michael@0 | 211 | for (typename HashMap::const_iterator i = map_a.begin(); |
michael@0 | 212 | i != map_a.end(); ++i) { |
michael@0 | 213 | typename HashMap::const_iterator j = map_b.find(i->first); |
michael@0 | 214 | if (j == map_b.end()) return false; |
michael@0 | 215 | if (i->second != j->second) return false; |
michael@0 | 216 | } |
michael@0 | 217 | return true; |
michael@0 | 218 | } |
michael@0 | 219 | |
michael@0 | 220 | // The following functions are useful for cleaning up STL containers |
michael@0 | 221 | // whose elements point to allocated memory. |
michael@0 | 222 | |
michael@0 | 223 | // STLDeleteElements() deletes all the elements in an STL container and clears |
michael@0 | 224 | // the container. This function is suitable for use with a vector, set, |
michael@0 | 225 | // hash_set, or any other STL container which defines sensible begin(), end(), |
michael@0 | 226 | // and clear() methods. |
michael@0 | 227 | // |
michael@0 | 228 | // If container is NULL, this function is a no-op. |
michael@0 | 229 | // |
michael@0 | 230 | // As an alternative to calling STLDeleteElements() directly, consider |
michael@0 | 231 | // STLElementDeleter (defined below), which ensures that your container's |
michael@0 | 232 | // elements are deleted when the STLElementDeleter goes out of scope. |
michael@0 | 233 | template <class T> |
michael@0 | 234 | void STLDeleteElements(T *container) { |
michael@0 | 235 | if (!container) return; |
michael@0 | 236 | STLDeleteContainerPointers(container->begin(), container->end()); |
michael@0 | 237 | container->clear(); |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | // Given an STL container consisting of (key, value) pairs, STLDeleteValues |
michael@0 | 241 | // deletes all the "value" components and clears the container. Does nothing |
michael@0 | 242 | // in the case it's given a NULL pointer. |
michael@0 | 243 | |
michael@0 | 244 | template <class T> |
michael@0 | 245 | void STLDeleteValues(T *v) { |
michael@0 | 246 | if (!v) return; |
michael@0 | 247 | for (typename T::iterator i = v->begin(); i != v->end(); ++i) { |
michael@0 | 248 | delete i->second; |
michael@0 | 249 | } |
michael@0 | 250 | v->clear(); |
michael@0 | 251 | } |
michael@0 | 252 | |
michael@0 | 253 | |
michael@0 | 254 | // The following classes provide a convenient way to delete all elements or |
michael@0 | 255 | // values from STL containers when they goes out of scope. This greatly |
michael@0 | 256 | // simplifies code that creates temporary objects and has multiple return |
michael@0 | 257 | // statements. Example: |
michael@0 | 258 | // |
michael@0 | 259 | // vector<MyProto *> tmp_proto; |
michael@0 | 260 | // STLElementDeleter<vector<MyProto *> > d(&tmp_proto); |
michael@0 | 261 | // if (...) return false; |
michael@0 | 262 | // ... |
michael@0 | 263 | // return success; |
michael@0 | 264 | |
michael@0 | 265 | // Given a pointer to an STL container this class will delete all the element |
michael@0 | 266 | // pointers when it goes out of scope. |
michael@0 | 267 | |
michael@0 | 268 | template<class STLContainer> class STLElementDeleter { |
michael@0 | 269 | public: |
michael@0 | 270 | STLElementDeleter(STLContainer *ptr) : container_ptr_(ptr) {} |
michael@0 | 271 | ~STLElementDeleter() { STLDeleteElements(container_ptr_); } |
michael@0 | 272 | private: |
michael@0 | 273 | STLContainer *container_ptr_; |
michael@0 | 274 | }; |
michael@0 | 275 | |
michael@0 | 276 | // Given a pointer to an STL container this class will delete all the value |
michael@0 | 277 | // pointers when it goes out of scope. |
michael@0 | 278 | |
michael@0 | 279 | template<class STLContainer> class STLValueDeleter { |
michael@0 | 280 | public: |
michael@0 | 281 | STLValueDeleter(STLContainer *ptr) : container_ptr_(ptr) {} |
michael@0 | 282 | ~STLValueDeleter() { STLDeleteValues(container_ptr_); } |
michael@0 | 283 | private: |
michael@0 | 284 | STLContainer *container_ptr_; |
michael@0 | 285 | }; |
michael@0 | 286 | |
michael@0 | 287 | |
michael@0 | 288 | // Forward declare some callback classes in callback.h for STLBinaryFunction |
michael@0 | 289 | template <class R, class T1, class T2> |
michael@0 | 290 | class ResultCallback2; |
michael@0 | 291 | |
michael@0 | 292 | // STLBinaryFunction is a wrapper for the ResultCallback2 class in callback.h |
michael@0 | 293 | // It provides an operator () method instead of a Run method, so it may be |
michael@0 | 294 | // passed to STL functions in <algorithm>. |
michael@0 | 295 | // |
michael@0 | 296 | // The client should create callback with NewPermanentCallback, and should |
michael@0 | 297 | // delete callback after it is done using the STLBinaryFunction. |
michael@0 | 298 | |
michael@0 | 299 | template <class Result, class Arg1, class Arg2> |
michael@0 | 300 | class STLBinaryFunction : public std::binary_function<Arg1, Arg2, Result> { |
michael@0 | 301 | public: |
michael@0 | 302 | typedef ResultCallback2<Result, Arg1, Arg2> Callback; |
michael@0 | 303 | |
michael@0 | 304 | STLBinaryFunction(Callback* callback) |
michael@0 | 305 | : callback_(callback) { |
michael@0 | 306 | assert(callback_); |
michael@0 | 307 | } |
michael@0 | 308 | |
michael@0 | 309 | Result operator() (Arg1 arg1, Arg2 arg2) { |
michael@0 | 310 | return callback_->Run(arg1, arg2); |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | private: |
michael@0 | 314 | Callback* callback_; |
michael@0 | 315 | }; |
michael@0 | 316 | |
michael@0 | 317 | // STLBinaryPredicate is a specialized version of STLBinaryFunction, where the |
michael@0 | 318 | // return type is bool and both arguments have type Arg. It can be used |
michael@0 | 319 | // wherever STL requires a StrictWeakOrdering, such as in sort() or |
michael@0 | 320 | // lower_bound(). |
michael@0 | 321 | // |
michael@0 | 322 | // templated typedefs are not supported, so instead we use inheritance. |
michael@0 | 323 | |
michael@0 | 324 | template <class Arg> |
michael@0 | 325 | class STLBinaryPredicate : public STLBinaryFunction<bool, Arg, Arg> { |
michael@0 | 326 | public: |
michael@0 | 327 | typedef typename STLBinaryPredicate<Arg>::Callback Callback; |
michael@0 | 328 | STLBinaryPredicate(Callback* callback) |
michael@0 | 329 | : STLBinaryFunction<bool, Arg, Arg>(callback) { |
michael@0 | 330 | } |
michael@0 | 331 | }; |
michael@0 | 332 | |
michael@0 | 333 | // Functors that compose arbitrary unary and binary functions with a |
michael@0 | 334 | // function that "projects" one of the members of a pair. |
michael@0 | 335 | // Specifically, if p1 and p2, respectively, are the functions that |
michael@0 | 336 | // map a pair to its first and second, respectively, members, the |
michael@0 | 337 | // table below summarizes the functions that can be constructed: |
michael@0 | 338 | // |
michael@0 | 339 | // * UnaryOperate1st<pair>(f) returns the function x -> f(p1(x)) |
michael@0 | 340 | // * UnaryOperate2nd<pair>(f) returns the function x -> f(p2(x)) |
michael@0 | 341 | // * BinaryOperate1st<pair>(f) returns the function (x,y) -> f(p1(x),p1(y)) |
michael@0 | 342 | // * BinaryOperate2nd<pair>(f) returns the function (x,y) -> f(p2(x),p2(y)) |
michael@0 | 343 | // |
michael@0 | 344 | // A typical usage for these functions would be when iterating over |
michael@0 | 345 | // the contents of an STL map. For other sample usage, see the unittest. |
michael@0 | 346 | |
michael@0 | 347 | template<typename Pair, typename UnaryOp> |
michael@0 | 348 | class UnaryOperateOnFirst |
michael@0 | 349 | : public std::unary_function<Pair, typename UnaryOp::result_type> { |
michael@0 | 350 | public: |
michael@0 | 351 | UnaryOperateOnFirst() { |
michael@0 | 352 | } |
michael@0 | 353 | |
michael@0 | 354 | UnaryOperateOnFirst(const UnaryOp& f) : f_(f) { |
michael@0 | 355 | } |
michael@0 | 356 | |
michael@0 | 357 | typename UnaryOp::result_type operator()(const Pair& p) const { |
michael@0 | 358 | return f_(p.first); |
michael@0 | 359 | } |
michael@0 | 360 | |
michael@0 | 361 | private: |
michael@0 | 362 | UnaryOp f_; |
michael@0 | 363 | }; |
michael@0 | 364 | |
michael@0 | 365 | template<typename Pair, typename UnaryOp> |
michael@0 | 366 | UnaryOperateOnFirst<Pair, UnaryOp> UnaryOperate1st(const UnaryOp& f) { |
michael@0 | 367 | return UnaryOperateOnFirst<Pair, UnaryOp>(f); |
michael@0 | 368 | } |
michael@0 | 369 | |
michael@0 | 370 | template<typename Pair, typename UnaryOp> |
michael@0 | 371 | class UnaryOperateOnSecond |
michael@0 | 372 | : public std::unary_function<Pair, typename UnaryOp::result_type> { |
michael@0 | 373 | public: |
michael@0 | 374 | UnaryOperateOnSecond() { |
michael@0 | 375 | } |
michael@0 | 376 | |
michael@0 | 377 | UnaryOperateOnSecond(const UnaryOp& f) : f_(f) { |
michael@0 | 378 | } |
michael@0 | 379 | |
michael@0 | 380 | typename UnaryOp::result_type operator()(const Pair& p) const { |
michael@0 | 381 | return f_(p.second); |
michael@0 | 382 | } |
michael@0 | 383 | |
michael@0 | 384 | private: |
michael@0 | 385 | UnaryOp f_; |
michael@0 | 386 | }; |
michael@0 | 387 | |
michael@0 | 388 | template<typename Pair, typename UnaryOp> |
michael@0 | 389 | UnaryOperateOnSecond<Pair, UnaryOp> UnaryOperate2nd(const UnaryOp& f) { |
michael@0 | 390 | return UnaryOperateOnSecond<Pair, UnaryOp>(f); |
michael@0 | 391 | } |
michael@0 | 392 | |
michael@0 | 393 | template<typename Pair, typename BinaryOp> |
michael@0 | 394 | class BinaryOperateOnFirst |
michael@0 | 395 | : public std::binary_function<Pair, Pair, typename BinaryOp::result_type> { |
michael@0 | 396 | public: |
michael@0 | 397 | BinaryOperateOnFirst() { |
michael@0 | 398 | } |
michael@0 | 399 | |
michael@0 | 400 | BinaryOperateOnFirst(const BinaryOp& f) : f_(f) { |
michael@0 | 401 | } |
michael@0 | 402 | |
michael@0 | 403 | typename BinaryOp::result_type operator()(const Pair& p1, |
michael@0 | 404 | const Pair& p2) const { |
michael@0 | 405 | return f_(p1.first, p2.first); |
michael@0 | 406 | } |
michael@0 | 407 | |
michael@0 | 408 | private: |
michael@0 | 409 | BinaryOp f_; |
michael@0 | 410 | }; |
michael@0 | 411 | |
michael@0 | 412 | template<typename Pair, typename BinaryOp> |
michael@0 | 413 | BinaryOperateOnFirst<Pair, BinaryOp> BinaryOperate1st(const BinaryOp& f) { |
michael@0 | 414 | return BinaryOperateOnFirst<Pair, BinaryOp>(f); |
michael@0 | 415 | } |
michael@0 | 416 | |
michael@0 | 417 | template<typename Pair, typename BinaryOp> |
michael@0 | 418 | class BinaryOperateOnSecond |
michael@0 | 419 | : public std::binary_function<Pair, Pair, typename BinaryOp::result_type> { |
michael@0 | 420 | public: |
michael@0 | 421 | BinaryOperateOnSecond() { |
michael@0 | 422 | } |
michael@0 | 423 | |
michael@0 | 424 | BinaryOperateOnSecond(const BinaryOp& f) : f_(f) { |
michael@0 | 425 | } |
michael@0 | 426 | |
michael@0 | 427 | typename BinaryOp::result_type operator()(const Pair& p1, |
michael@0 | 428 | const Pair& p2) const { |
michael@0 | 429 | return f_(p1.second, p2.second); |
michael@0 | 430 | } |
michael@0 | 431 | |
michael@0 | 432 | private: |
michael@0 | 433 | BinaryOp f_; |
michael@0 | 434 | }; |
michael@0 | 435 | |
michael@0 | 436 | template<typename Pair, typename BinaryOp> |
michael@0 | 437 | BinaryOperateOnSecond<Pair, BinaryOp> BinaryOperate2nd(const BinaryOp& f) { |
michael@0 | 438 | return BinaryOperateOnSecond<Pair, BinaryOp>(f); |
michael@0 | 439 | } |
michael@0 | 440 | |
michael@0 | 441 | // Translates a set into a vector. |
michael@0 | 442 | template<typename T> |
michael@0 | 443 | std::vector<T> SetToVector(const std::set<T>& values) { |
michael@0 | 444 | std::vector<T> result; |
michael@0 | 445 | result.reserve(values.size()); |
michael@0 | 446 | result.insert(result.begin(), values.begin(), values.end()); |
michael@0 | 447 | return result; |
michael@0 | 448 | } |
michael@0 | 449 | |
michael@0 | 450 | #endif // BASE_STL_UTIL_INL_H_ |