Welche C ++ Standard Library-Wrapper-functionen verwenden Sie?

Diese Frage , die heute Morgen gestellt wurde, ließ mich fragen, welche functionen Ihrer Meinung nach in der C ++ – Standardbibliothek fehlen und wie Sie die Lücken mit Wrapper-functionen gefüllt haben. Zum Beispiel hat meine eigene Utility-Bibliothek diese function für Vektoranhang:

template  std::vector & operator += ( std::vector & v1, const std::vector  & v2 ) { v1.insert( v1.end(), v2.begin(), v2.end() ); return v1; } 

und dies zum Löschen (mehr oder weniger) jeder Art – besonders nützlich für Dinge wie std :: stack:

 template  void Clear( C & c ) { c = C(); } 

Ich habe ein paar mehr, aber ich bin daran interessiert, welche Sie verwenden? Bitte beschränken Sie die Antworten auf Wrapper- functionen – dh nicht mehr als ein paar Zeilen Code.

boost :: array

enthält (Container, val) (ziemlich einfach, aber praktisch).

 template bool contains(const C& container, const T& val) { return std::find(std::begin(container), std::end(container), val) != std::end(container); } 

remove_unstable (Anfang, Ende, Wert)

Eine schnellere Version von std :: remove mit der Ausnahme, dass die Reihenfolge der verbleibenden Objekte nicht beibehalten wird.

 template  T remove_unstable(T start, T stop, const typename T::value_type& val){ while(start != stop) { if (*start == val) { --stop; ::std::iter_swap(start, stop); } else { ++start; } } return stop; } 

(Im Fall eines Vektors von Pod-Typen (int, float usw.) und fast alle Objekte werden entfernt, std :: remove könnte schneller sein).

Ziemlich oft würde ich den Vektor als eine Menge von Elementen in einer bestimmten Reihenfolge verwenden (und natürlich, wenn ich keine schnellen Check-is-Elemente-in-the-set-Tests benötige). In diesen Fällen ist das Aufrufen von Erase () Zeitverschwendung, da die Elemente neu angeordnet werden und mir die Reihenfolge egal ist. Das ist, wenn die O (1) -function unten nützlich ist – verschieben Sie einfach das letzte Element an der Position desjenigen, das Sie löschen möchten:

 template void erase_unordered(std::vector& v, size_t index) { v[index] = v.back(); v.pop_back(); } 
 template < class T > class temp_value { public : temp_value(T& var) : _var(var), _original(var) {} ~temp_value() { _var = _original; } private : T& _var; T _original; temp_value(const temp_value&); temp_value& operator=(const temp_value&); }; 

Ok, da es scheint, dass dies nicht so geradlinig ist wie ich dachte, hier ist eine Erklärung:
In seinem Konstruktor speichert temp_value einen Verweis auf eine Variable und eine Kopie des ursprünglichen Werts der Variablen. In seinem Destruktor stellt er die referenzierte Variable auf ihren ursprünglichen Wert zurück. Unabhängig davon, was Sie mit der Variablen zwischen Konstruktion und Zerstörung getan haben, wird sie zurückgesetzt, wenn das Objekt temp_value den temp_value .
Benutze es so:

 void f(some_type& var) { temp_value restorer(var); // remembers var's value // change var as you like g(var); // upon destruction restorer will restore var to its original value } 

Hier ist ein anderer Ansatz, der den Trick des Bereichs-Schutz verwendet:

 namespace detail { // use scope-guard trick class restorer_base { public: // call to flag the value shouldn't // be restored at destruction void dismiss(void) const { mDismissed = true; } protected: // creation restorer_base(void) : mDismissed(false) {} restorer_base(const restorer_base& pOther) : mDismissed(pOther.is_dismissed()) { // take "ownership" pOther.dismiss(); } ~restorer_base(void) {} // non-virtual // query bool is_dismissed(void) const { return mDismissed; } private: // not copy-assignable, copy-constructibility is ok restorer_base& operator=(const restorer_base&); mutable bool mDismissed; }; // generic single-value restorer, could be made // variadic to store and restore several variables template  class restorer_holder : public restorer_base { public: restorer_holder(T& pX) : mX(pX), mValue(pX) {} ~restorer_holder(void) { if (!is_dismissed()) mX = mValue; } private: // not copy-assignable, copy-constructibility is ok restorer_holder& operator=(const restorer_holder&); T& mX; T mValue; }; } // store references to generated holders typedef const detail::restorer_base& restorer; // generator (could also be made variadic) template  detail::restorer_holder store(T& pX) { return detail::restorer_holder(pX); } 

Es ist nur ein bisschen mehr Kesselplatte-Code, aber ermöglicht eine sauberere Verwendung:

 #include  template  void print(const T& pX) { std::cout < < pX << std::endl; } void foo(void) { double d = 10.0; double e = 12.0; print(d); print(e); { restorer f = store(d); restorer g = store(e); d = -5.0; e = 3.1337; print(d); print(e); g.dismiss(); } print(d); print(e); } int main(void) { foo(); int i = 5; print(i); { restorer r = store(i); i *= 123; print(i); } print(i); } 

Es entfernt jedoch seine Fähigkeit, in einer class verwendet zu werden.


Hier ist ein dritter Weg, um den gleichen Effekt zu erzielen (der nicht unter den Problemen potentieller Wurfdestruktoren leidet):

Implementierung:

 //none -- it is built into the language 

Verwendung:

 #include  template  void print(const T& pX) { std::cout < < pX << std::endl; } void foo(void) { double d = 10.0; double e = 12.0; print(d); print(e); { double f(d); double g(e); f = -5.0; g = 3.1337; print(f); print(g); e = std::move(g); } print(d); print(e); } int main(void) { foo(); int i = 5; print(i); { int r(i); r *= 123; print(r); } print(i); } 

Nicht wirklich ein Wrapper, aber die berüchtigte fehlende copy_if . Von hier aus

 template Out copy_if(In first, In last, Out res, Pred Pr) { while (first != last) { if (Pr(*first)) { *res++ = *first; } ++first; } return res; } 
 template< typename T, std::size_t sz > inline T* begin(T (&array)[sz]) {return array;} template< typename T, std::size_t sz > inline T* end (T (&array)[sz]) {return array + sz;} 

Manchmal fühle ich mich wie in der begin() und end() Hölle. Ich hätte gerne einige functionen wie:

 template void sort(T& x) { std::sort(x.begin(), x.end()); } 

und andere ähnliche für std::find , std::for_each und im Grunde alle STL-Algorithmen.

Ich glaube, dass sort(x) viel schneller zu lesen ist als sort(x.begin(), x.end()) .

Ich benutze diesen hier nicht mehr so ​​oft, aber es war ein Grundnahrungsmittel:

 template std::string make_string(const T& data) { std::ostringstream stream; stream < < data; return stream.str(); } 

Wird mit mehr aktualisieren, wenn ich mich an sie erinnere. : P

Die Utility-function in jeder Toolbox ist natürlich copy_if . Nicht wirklich ein Wrapper.

Ein anderer Helfer, den ich häufig benutze, ist deleter , ein Funktor, den ich mit std::for_each , um alle pointers in einem Container zu löschen.

[Bearbeiten] Durch meine “sth.h” graben fand ich auch vector StringSplit(wstring const&, wchar_t);

Ich habe einen Header, der Folgendes in den Namensraum “util” schreibt:

 // does a string contain another string inline bool contains(const std::string &s1, const std::string &s2) { return s1.find(s2) != std::string::npos; } // remove trailing whitespace inline std::string &rtrim(std::string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); return s; } // remove leading whitespace inline std::string &ltrim(std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); return s; } // remove whitespace from both ends inline std::string &trim(std::string &s) { return ltrim(rtrim(s)); } // split a string based on a delimeter and return the result (you pass an existing vector for the results) inline std::vector &split(const std::string &s, char delim, std::vector &elems) { std::stringstream ss(s); std::string item; while(std::getline(ss, item, delim)) { elems.push_back(item); } return elems; } // same as above, but returns a vector for you inline std::vector split(const std::string &s, char delim) { std::vector elems; return split(s, delim, elems); } // does a string end with another string inline bool endswith(const std::string &s, const std::string &ending) { return ending.length() < = s.length() && s.substr(s.length() - ending.length()) == ending; } // does a string begin with another string inline bool beginswith(const std::string &s, const std::string &start) { return s.compare(0, start.length(), start) == 0; } 

Der infamously fehlende erase :

  template < class Container, class Value > void erase(Container& ioContainer, Value const& iValue) { ioContainer.erase( std::remove(ioContainer.begin(), ioContainer.end(), iValue), ioContainer.end()); } // erase template < class Container, class Pred > void erase_if(Container& ioContainer, Pred iPred) { ioContainer.erase( std::remove_if(ioContainer.begin(), ioContainer.end(), iPred), ioContainer.end()); } // erase_if 

Wrapping sprintf

 string example = function("
  • Buffer at: 0x%08X
  • ", 42, &some_obj); // 'function' is one of the functions below: Format or stringf

    Das Ziel besteht darin, die Formatierung von der Ausgabe zu entkoppeln, ohne mit Sprintf und seiner Art in Konflikt zu geraten. Es ist nicht schön, aber es ist sehr nützlich, besonders wenn deine Kodierungsrichtlinien Iostreams verbieten.


    Hier ist eine Version, die bei Bedarf von Neil Butterworth zuordnet. [Revisionsverlauf für Mikes Version ansehen, die ich als Teilmenge der verbleibenden zwei entfernt habe. Es ist ähnlich wie bei Neil, außer dass letzteres ausnahmesicher ist, indem man vector anstelle von delete [] verwendet: string’s ctor wird bei einem Zuweisungserrors casting. Mike verwendet auch die gleiche Technik, die später gezeigt wird, um die Größe vorne zu bestimmen. -RP]

     string Format( const char * fmt, ... ) { const int BUFSIZE = 1024; int size = BUFSIZE, rv = -1; vector  buf; do { buf.resize( size ); va_list valist; va_start( valist, fmt ); // if _vsnprintf() returns < 0, the buffer wasn't big enough // so increase buffer size and try again // NOTE: MSFT's _vsnprintf is different from C99's vsnprintf, // which returns non-negative on truncation // http://msdn.microsoft.com/en-us/library/1kt27hek.aspx rv = _vsnprintf( &buf[0], size, fmt, valist ); va_end( valist ); size *= 2; } while( rv < 0 ); return string( &buf[0] ); } 

    Hier ist eine Version, die von Roger Pate die benötigte Größe vorne bestimmt. Dies erfordert schreibbare std :: strings, die von gängigen Implementierungen bereitgestellt werden, aber explizit von C ++ 0x benötigt werden. [Revisionsverlauf für die Version von Marcus anzeigen, die ich entfernt habe, da sie etwas anders ist, aber im Wesentlichen eine Teilmenge des Folgenden ist. -RP]

    Implementierung

     void vinsertf(std::string& s, std::string::iterator it, char const* fmt, int const chars_needed, va_list args ) { using namespace std; int err; // local error code if (chars_needed < 0) err = errno; else { string::size_type const off = it - s.begin(); // save iterator offset if (it == s.end()) { // append to the end s.resize(s.size() + chars_needed + 1); // resize, allow snprintf's null it = s.begin() + off; // iterator was invalidated err = vsnprintf(&*it, chars_needed + 1, fmt, args); s.resize(s.size() - 1); // remove snprintf's null } else { char saved = *it; // save char overwritten by snprintf's null s.insert(it, chars_needed, '\0'); // insert needed space it = s.begin() + off; // iterator was invalidated err = vsnprintf(&*it, chars_needed + 1, fmt, args); *(it + chars_needed) = saved; // restore saved char } if (err >= 0) { // success return; } err = errno; it = s.begin() + off; // above resize might have invalidated 'it' // (invalidation is unlikely, but allowed) s.erase(it, it + chars_needed); } string what = stringf("vsnprintf: [%d] ", err); what += strerror(err); throw runtime_error(what); } 

    Öffentliche Schnittstelle

     std::string stringf(char const* fmt, ...) { using namespace std; string s; va_list args; va_start(args, fmt); int chars_needed = vsnprintf(0, 0, fmt, args); va_end(args); va_start(args, fmt); try { vinsertf(s, s.end(), fmt, chars_needed, args); } catch (...) { va_end(args); throw; } va_end(args); return s; } // these have nearly identical implementations to stringf above: std::string& appendf(std::string& s, char const* fmt, ...); std::string& insertf(std::string& s, std::string::iterator it, char const* fmt, ...); 

    Das Dienstprogramm is_sorted , um Container zu testen, bevor Algorithmen wie include is_sorted , die einen sortierten Eintrag erwarten:

      template < class FwdIt > bool is_sorted(FwdIt iBegin, FwdIt iEnd) { typedef typename std::iterator_traits::value_type value_type; return adjacent_find(iBegin, iEnd, std::greater()) == iEnd; } // is_sorted template < class FwdIt, class Pred > bool is_sorted_if(FwdIt iBegin, FwdIt iEnd, Pred iPred) { if (iBegin == iEnd) return true; FwdIt aIt = iBegin; for (++aIt; aIt != iEnd; ++iBegin, ++aIt) { if (!iPred(*iBegin, *aIt)) return false; } return true; } // is_sorted_if 

    Ja, ich weiß, wäre besser, das Prädikat zu negieren und die Prädikat-Version von adjacent_find 🙂

    Auf jeden Fall boost :: addressof

     //! \brief Fills reverse_map from map, so that all keys of map // become values of reverse_map and all values become keys. //! \note This presumes that there is a one-to-one mapping in map! template< typename T1, typename T2, class TP1, class TA1, class TP2, class TA2 > inline void build_reverse_map( const std::map& map , std::map& reverse_map) { typedef std::map map_type; typedef std::map r_map_type; typedef typename r_map_type::value_type r_value_type; for( typename map_type::const_iterator it=map.begin(), end=map.end(); it!=end; ++it ) { const r_value_type v(it->second,it->first); const bool was_new = reverse_map.insert(v).second; assert(was_new); } } 

    Mit Blick auf mein stl_util.h , viele der Klassiker (Deleter-functionen, copy_if ), und auch dieses (wahrscheinlich auch ziemlich häufig, aber ich sehe es nicht in den Antworten bisher) für das Durchsuchen einer Karte und die Rückgabe von entweder der gefundene Wert oder ein Standardwert, ala get in Python’s dict :

     template inline V search_map(const std::map& mapping, const K& key, const V& null_result = V()) { typename std::map::const_iterator i = mapping.find(key); if(i == mapping.end()) return null_result; return i->second; } 

    Das standardmäßige null_result eines standardkonstruierten V ist dem Verhalten von std::map ‘s operator[] sehr ähnlich, aber das ist nützlich, wenn die Map const (für mich üblich) ist, oder wenn das default-konstruierte V ist nicht das Richtige zu benutzen.

    Hier sind meine Extra-Utils, die auf einem boost.range’ish std-algo Wrapper basieren, den Sie für einige functionen benötigen könnten. (das ist trivial zu schreiben, das ist das interessante Zeug)

     #pragma once /** @file @brief Defines various utility classes/functions for handling ranges/function objects in addition to bsRange (which is a ranged version of the \ header) Items here uses a STL/boost-style naming due to their 'templatised' nature. If template variable is R, anything matching range_concept can be used. If template variable is C, it must be a container object (supporting C::erase()) */ #include  #include  #include  namespace boost { struct use_default; template class iterator_range; #pragma warning(disable: 4348) // redeclaration of template default parameters (this clashes with fwd-decl in boost/transform_iterator.hpp) template < class UnaryFunction , class Iterator , class Reference = use_default , class Value = use_default > class transform_iterator; template < class Iterator , class Value = use_default , class Category = use_default , class Reference = use_default , class difference = use_default > class indirect_iterator; template struct range_iterator; template < class Incrementable , class CategoryOrTraversal = use_default , class difference = use_default > class counting_iterator; template  class filter_iterator; } namespace orz { /// determines if any value that compares equal exists in container template inline bool contains(const R& r, const T& v) { return std::find(boost::begin(r), boost::end(r), v) != boost::end(r); } /// determines if predicate evaluates to true for any value in container template inline bool contains_if(const R& r, const F& f) { return std::find_if(boost::begin(r), boost::end(r), f) != boost::end(r); } /// insert elements in range r at end of container c template inline void insert(C& c, const R& r) { c.insert(c.end(), boost::begin(r), boost::end(r)); } /// copy elements that match predicate template inline void copy_if(I i, I end, O& o, const P& p) { for (; i != end; ++i) { if (p(*i)) { *o = *i; ++o; } } } /// copy elements that match predicate template inline void copy_if(R& r, O& o, const P& p) { copy_if(boost::begin(r), boost::end(r), o, p); } /// erases first element that compare equal template inline bool erase_first(C& c, const T& v) { typename C::iterator end = boost::end(c); typename C::iterator i = std::find(boost::begin(c), end, v); return i != c.end() ? c.erase(i), true : false; } /// erases first elements that match predicate template inline bool erase_first_if(C& c, const F& f) { typename C::iterator end = boost::end(c); typename C::iterator i = std::find_if(boost::begin(c), end, f); return i != end ? c.erase(i), true : false; } /// erase all elements (doesn't deallocate memory for std::vector) template inline void erase_all(C& c) { c.erase(c.begin(), c.end()); } /// erase all elements that compare equal template int erase(C& c, const T& value) { int n = 0; for (boost::range_iterator::type i = boost::begin(c); i != boost::end(c);) { if (*i == value) { i = c.erase(i); ++n; } else { ++i; } } return n; } /// erase all elements that match predicate template int erase_if(C& c, const F& f) { int n = 0; for (boost::range_iterator::type i = boost::begin(c); i != boost::end(c);) { if (f(*i)) { i = c.erase(i); ++n; } else { ++i; } } return n; } /// erases all consecutive duplicates from container (sort container first to get all) template inline int erase_duplicates(C& c) { boost::range_iterator::type i = std::unique(c.begin(), c.end()); typename C::size_type n = std::distance(i, c.end()); c.erase(i, c.end()); return n; } /// erases all consecutive duplicates, according to predicate, from container (sort container first to get all) template inline int erase_duplicates_if(C& c, const F& f) { boost::range_iterator::type i = std::unique(c.begin(), c.end(), f); typename C::size_type n = std::distance(i, c.end()); c.erase(i, c.end()); return n; } /// fill but for the second value in each pair in range template inline void fill_second(R& r, const V& v) { boost::range_iterator::type i(boost::begin(r)), end(boost::end(r)); for (; i != end; ++i) { i->second = v; } } /// applying function to corresponding pair through both ranges, min(r1.size(), r2,size()) applications template void for_each2(R1& r1, R2& r2, const F& f) { boost::range_iterator::type i(boost::begin(r1)), i_end(boost::end(r1)); boost::range_iterator::type j(boost::begin(r2)), j_end(boost::end(r2)); for(;i != i_end && j != j_end; ++i, ++j) { f(*i, *j); } } /// applying function to corresponding pair through both ranges, min(r1.size(), r2,size()) applications template void for_each3(R1& r1, R2& r2, R3& r3, const F& f) { boost::range_iterator::type i(boost::begin(r1)), i_end(boost::end(r1)); boost::range_iterator::type j(boost::begin(r2)), j_end(boost::end(r2)); boost::range_iterator::type k(boost::begin(r3)), k_end(boost::end(r3)); for(;i != i_end && j != j_end && k != k_end; ++i, ++j, ++k) { f(*i, *j, *k); } } /// applying function to each possible permutation of objects, r1.size() * r2.size() applications template void for_each_permutation(R1 & r1, R2& r2, const F& f) { typedef boost::range_iterator::type R1_iterator; typedef boost::range_iterator::type R2_iterator; R1_iterator end_1 = boost::end(r1); R2_iterator begin_2 = boost::begin(r2); R2_iterator end_2 = boost::end(r2); for(R1_iterator i = boost::begin(r1); i != end_1; ++i) { for(R2_iterator j = begin_2; j != end_2; ++j) { f(*i, *j); } } } template  inline boost::iterator_range::type > > make_indirect_range(R& r) { return boost::iterator_range::type > > (r); } template  inline boost::iterator_range::type> > make_transform_range(R& r, const F& f) { return boost::iterator_range::type> >( boost::make_transform_iterator(boost::begin(r), f), boost::make_transform_iterator(boost::end(r), f)); } template  inline boost::iterator_range > make_counting_range(T begin, T end) { return boost::iterator_range >( boost::counting_iterator(begin), boost::counting_iterator(end)); } template  inline boost::iterator_range::type> > make_filter_range(R& r, const F& f) { return boost::iterator_range::type> >( boost::make_filter_iterator(f, boost::begin(r), boost::end(r)), boost::make_filter_iterator(f, boost::end(r), boost::end(r))); } namespace detail { template T* get_pointer(T& p) { return &p; } } /// compare member function/variable equal to value. Create using @ref mem_eq() to avoid specfying types template struct mem_eq_type { mem_eq_type(const P& p, const V& v) : m_p(p), m_v(v) { } template bool operator()(const T& a) const { using boost::get_pointer; using orz::detail::get_pointer; return (get_pointer(a)->*m_p) == m_v; } P m_p; V m_v; }; template mem_eq_type

    mem_eq(const P& p, const V& v) { return mem_eq_type

    (p, v); } /// helper macro to define function objects that compare member variables of a class #define ORZ_COMPARE_MEMBER(NAME, OP) \ template \ struct NAME##_type \ { \ NAME##_type(const P&p) : m_p(p) {} \ template \ bool operator()(const T& a, const T& b) const { \ return (a.*m_p) OP (b.*m_p); \ } \ P m_p; \ }; \ template \ NAME##_type

    NAME(const P& p) { return NAME##_type

    (p); } #define ORZ_COMPARE_MEMBER_FN(NAME, OP) \ template \ struct NAME##_type \ { \ NAME##_type(const P&p) : m_p(p) {} \ template \ bool operator()(const T& a, const T& b) const { \ return (a.*m_p)() OP (b.*m_p)(); \ } \ P m_p; \ }; \ template \ NAME##_type

    NAME(const P& p) { return NAME##_type

    (p); } /// helper macro to wrap range functions as function objects (value return) #define ORZ_RANGE_WRAP_VALUE_2(FUNC, RESULT) \ struct FUNC##_ \ { \ typedef RESULT result_type; \ template \ inline RESULT operator() (R& r, const F& f) const \ { \ return FUNC(r, f); \ } \ }; /// helper macro to wrap range functions as function objects (void return) #define ORZ_RANGE_WRAP_VOID_2(FUNC) \ struct FUNC##_ \ { \ typedef void result_type; \ template \ inline void operator() (R& r, const F& f) const \ { \ FUNC(r, f); \ } \ }; /// helper macro to wrap range functions as function objects (void return, one argument) #define ORZ_RANGE_WRAP_VOID_1(FUNC) \ struct FUNC##_ \ { \ typedef void result_type; \ template \ inline void operator() (R& r) const \ { \ FUNC(r); \ } \ }; ORZ_RANGE_WRAP_VOID_2(for_each); ORZ_RANGE_WRAP_VOID_1(erase_all); ORZ_RANGE_WRAP_VALUE_2(contains, bool); ORZ_RANGE_WRAP_VALUE_2(contains_if, bool); ORZ_COMPARE_MEMBER(mem_equal, ==) ORZ_COMPARE_MEMBER(mem_not_equal, !=) ORZ_COMPARE_MEMBER(mem_less, < ) ORZ_COMPARE_MEMBER(mem_greater, >) ORZ_COMPARE_MEMBER(mem_lessequal, < =) ORZ_COMPARE_MEMBER(mem_greaterequal, >=) ORZ_COMPARE_MEMBER_FN(mem_equal_fn, ==) ORZ_COMPARE_MEMBER_FN(mem_not_equal_fn, !=) ORZ_COMPARE_MEMBER_FN(mem_less_fn, < ) ORZ_COMPARE_MEMBER_FN(mem_greater_fn, >) ORZ_COMPARE_MEMBER_FN(mem_lessequal_fn, < =) ORZ_COMPARE_MEMBER_FN(mem_greaterequal_fn, >=) #undef ORZ_COMPARE_MEMBER #undef ORZ_RANGE_WRAP_VALUE_2 #undef ORZ_RANGE_WRAP_VOID_1 #undef ORZ_RANGE_WRAP_VOID_2 }

    I seem to need a Cartesian product, for example {A, B}, {1, 2} -> {(A,1), (A,2), (B,1), (B,2)}

     // OutIt needs to be an iterator to a container of std::pair template  OutIt cartesian_product(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt out) { for (; first1 != last1; ++first1) for (InIt2 it = first2; it != last2; ++it) *out++ = std::make_pair(*first1, *it); return out; } 

    I would call such an append function by its name and would use operator+= , operator*= and so on for element-wise operations, such as:

      template inline void operator+= (std::vector& vec1, const X& value) { std::transform( vec1.begin(), vec1.end(), vec1.begin(), std::bind2nd(std::plus(),value) ); } template inline void operator+= (std::vector& vec1, const std::vector& vec2) { std::transform( vec1.begin(), vec1.end(), vec2.begin(), vec1.begin(), std::plus() ); } 

    some other simple and obvious wrappers as implied before:

      template inline void sort_and_unique(std::vector &vec) { std::sort( vec.begin(), vec.end() ); vec.erase( std::unique( vec.begin(), vec.end() ), vec.end() ); } template inline void clear_vec(std::vector &vec) { std::vector().swap(vec); } template inline void trim_vec(std::vector &vec, std::size_t new_size) { if (new_size(vec.begin(),vec.begin() + new_size).swap(vec); else std::vector(vec).swap(vec); } 

    Insert a new item and return it, useful for simple move semantics like push_back(c).swap(value) and related cases.

     template typename C::value_type& push_front(C& container) { container.push_front(typename C::value_type()); return container.front(); } template typename C::value_type& push_back(C& container) { container.push_back(typename C::value_type()); return container.back(); } template typename C::value_type& push_top(C& container) { container.push(typename C::value_type()); return container.top(); } 

    Pop and return an item:

     template typename C::value_type pop_front(C& container) { typename C::value_type copy (container.front()); container.pop_front(); return copy; } template typename C::value_type pop_back(C& container) { typename C::value_type copy (container.back()); container.pop_back(); return copy; } template typename C::value_type pop_top(C& container) { typename C::value_type copy (container.top()); container.pop(); return copy; } 

    IMO there needs to be more functionality for pair :

     #ifndef pair_iterator_h_ #define pair_iterator_h_ #include  #include  #include  // pair -> T1 template  struct PairGetFirst : public std::unary_function { typename typename PairType::first_type& operator()(PairType& arg) const { return arg.first; } const typename PairType::first_type& operator()(const PairType& arg) const { return arg.first; } }; // pair -> T2 template  struct PairGetSecond : public std::unary_function { typename PairType::second_type& operator()(PairType& arg) const { return arg.second; } const typename PairType::second_type& operator()(const PairType& arg) const { return arg.second; } }; // iterator over pair -> iterator over T1 template  boost::transform_iterator::value_type>, Iter> make_first_iterator(Iter i) { return boost::make_transform_iterator(i, PairGetFirst::value_type>()); } // iterator over pair -> iterator over T2 template  boost::transform_iterator::value_type>, Iter> make_second_iterator(Iter i) { return boost::make_transform_iterator(i, PairGetSecond::value_type>()); } // T1 -> pair template  class InsertIntoPair1st : public std::unary_function > { public: InsertIntoPair1st(const SecondType& second_element) : second_(second_element) {} result_type operator()(const FirstType& first_element) { return result_type(first_element, second_); } private: SecondType second_; }; // T2 -> pair template  class InsertIntoPair2nd : public std::unary_function > { public: InsertIntoPair2nd(const FirstType& first_element) : first_(first_element) {} result_type operator()(const SecondType& second_element) { return result_type(first_, second_element); } private: FirstType first_; }; #endif // pair_iterator_h_ 
     template  size_t bytesize(std::vector const& v) { return sizeof(T) * v.size(); } 

    If you need to use a lot of functions that take pointer + number of bytes, it’s always just

     fun(vec.data(), bytesize(vec)); 

    Duplicate a string with *:

     std::string operator*(std::string s, size_t n) { std::stringstream ss; for (size_t i=0; i 

    One of my favorite is the Transposer that finds a transpose of a tuple of containers of the same size. That is, if you have a tuple,vector> , it converts it into a vector> . Comes handy in XML programming. Hier ist, wie ich es gemacht habe.

     #include  #include  #include  #include  #include  #include  #include  #include  #include  using namespace boost; template  struct GetTransposeTuple; template <> struct GetTransposeTuple { typedef tuples::null_type type; }; template  struct GetTransposeTuple { typedef typename TupleOfVectors::head_type Head; typedef typename TupleOfVectors::tail_type Tail; typedef typename tuples::cons::type::value_type, typename GetTransposeTuple::type> type; }; template ::type, unsigned int TUPLE_INDEX = 0> struct Transposer : Transposer  { typedef typename remove_reference::type HeadContainer; typedef typename TupleOfVectors::tail_type Tail; typedef Transposer super; typedef std::vector Transpose; Transposer(TupleOfVectors const & tuple) : super(tuple.get_tail()), head_container_(tuple.get_head()), head_iter_(head_container_.begin()) {} Transpose get_transpose () { Transpose tran; tran.reserve(head_container_.size()); for(typename HeadContainer::const_iterator iter = head_container_.begin(); iter != head_container_.end(); ++iter) { ValueTypeTuple vtuple; this->populate_tuple(vtuple); tran.push_back(vtuple); } return tran; } private: HeadContainer const & head_container_; typename HeadContainer::const_iterator head_iter_; protected: void populate_tuple(ValueTypeTuple & vtuple) { if(head_iter_ == head_container_.end()) throw std::runtime_error("Container bound exceeded."); else { vtuple.get() = *head_iter_++; super::populate_tuple (vtuple); } } }; template  struct Transposer  { void populate_tuple(ValueTypeTuple &) {} Transposer (tuples::null_type const &) {} }; template  typename Transposer::Transpose transpose (TupleOfVectors const & tupleofv) { return Transposer(tupleofv).get_transpose(); } int main (void) { typedef std::vector Vint; typedef std::list Lfloat; typedef std::vector Vlong; Vint vint; Lfloat lfloat; Vlong vlong; std::generate_n(std::back_inserter(vint), 10, rand); std::generate_n(std::back_inserter(lfloat), 10, rand); std::generate_n(std::back_inserter(vlong), 10, rand); typedef tuples::tuple TupleOfV; typedef GetTransposeTuple::type TransposeTuple; Transposer::Transpose tran = transpose(make_tuple(vint, lfloat, vlong)); // Or alternatively to avoid copying // transpose(make_tuple(ref(vint), ref(lfloat), ref(vlong))); std::copy(tran.begin(), tran.end(), std::ostream_iterator(std::cout, "\n")); return 0; } 

    Not sure if these qualify as std wrappers, but my commonly used helper functions are:

     void split(string s, vector parts, string delims); string join(vector& parts, string delim); int find(T& array, const V& value); void assert(bool condition, string message); V clamp(V value, V minvalue, V maxvalue); string replace(string s, string from, string to); const char* stristr(const char* a,const char*b); string trim(string str); T::value_type& dyn(T& array,int index); 

    T and V here are template arguments. The last function works the same way as []-operator, but with automating resizing to fit needed index.

    Similar to what people posted before, I have convenience overloads of algorithms for simplifying passing iterator arguments. I call algorithms like this:

     for_each(iseq(vec), do_it()); 

    I overloaded all the algorithms such that they take a single parameter of type input_sequence_range<> instead of the two input iterators (input as in anything that isn’t mere output).

     template struct input_sequence_range : public std::pair { input_sequence_range(In first, In last) : std::pair(first, last) { } }; 

    And this is how iseq() works:

     template input_sequence_range iseq(const C& c) { return input_sequence_range(c.begin(), c.end()); } 

    Similarly, I have specializations for

    • const_iterators
    • pointers (primitive arrays)
    • stream iterators
    • any range [begin,end) just for a uniform use: use iseq() for everything

    Unordered erase for std::vector . The most efficient way to erase an element from a vector but it does not preserve the order of elements. I didn’t see the point of extending it to other containers since most don’t have the same penalty for removing items from the middle. It’s similar to some other templates already posted but it uses std::swap to move items instead of copying.

     template void unordered_erase(std::vector& vec, const typename std::vector::iterator& it) { if (it != vec.end()) // if vec is empty, begin() == end() { std::swap(vec.back(), *it); vec.pop_back(); } } 

    Signum returns the sign of a type. Returns -1 for negative, 0 for zero and 1 for positive.

     template  int signum(T val) { return (val > T(0)) - (val < T(0)); } 

    Clamp is pretty self explanatory, it clamps a value so that it lies within the given range. It boggles my mind that the Standard Library includes min and max but not clamp

     template T clamp(const T& value, const T& lower, const T& upper) { return value < lower ? lower : (value > upper ? upper : value); }