contrib/mul/mbl/mbl_stl.h
Go to the documentation of this file.
00001 // This is mul/mbl/mbl_stl.h
00002 #ifndef mbl_stl_h_
00003 #define mbl_stl_h_
00004 //:
00005 // \file
00006 // \brief Useful things missing from vcl_algorithm, etc.
00007 // \author iscott
00008 // \date  Dec 2001
00009 // Actually, this is mostly an opportunity to mess around in STL to produce code
00010 // which would be much simpler in ordinary C++. Stroustrup assures us that
00011 // this approach is faster in general - which I don't really believe.
00012 //
00013 // Added quite a few little functors mainly to do with iterating through maps
00014 // for example a version of the non-standard select1st and select2nd
00015 // 30 April 2004
00016 // Martin Roberts
00017 
00018 #include <vcl_functional.h>
00019 #include <vcl_vector.h>
00020 // not used? #include <vcl_iterator.h>
00021 #include <vcl_ostream.h>
00022 
00023 //: Fill an output sequence with incrementing values.
00024 // A bit like vcl_fill, but after each assignment, the value is incremented.
00025 // \return the next value in the sequence.
00026 template<class Out, class T>
00027 inline T mbl_stl_increments(Out first, Out last, T init)
00028 {
00029   for (; first != last; ++first, ++init) *first = init;
00030   return init;
00031 }
00032 
00033 //: Fill the first n values of an output sequence with incrementing values.
00034 // A bit like vcl_fill_n, but after each assignment,
00035 // the value is incremented.
00036 // \return the next value in the sequence.
00037 template<class Out, class Size, class T>
00038 inline T mbl_stl_increments_n(Out first, Size n, T init)
00039 {
00040   for (; 0 < n; ++first, --n, ++init) *first = init;
00041   return init;
00042 }
00043 
00044 //: Produces a first order sequence from the supplied unary function.
00045 // The value produced at a given step is a function of the previous value.
00046 // E.g. the following is equivalent to using mbl_stl_increments
00047 // \code
00048 // mbl_stl_sequence(A.begin(), A.end(), vcl_bind1st(vcl_plus<unsigned>(), 1u), 0u);
00049 // \endcode
00050 // \return the next value in the sequence.
00051 template<class Out, class T, class UnOp>
00052 inline T mbl_stl_sequence(Out first, Out last, UnOp op, T init)
00053 {
00054   for (;first != last; ++first, init = op(init)) *first = init;
00055   return init;
00056 }
00057 
00058 //: Produces a first order sequence of size n from the supplied function.
00059 // The value produced at a given step is a function of the previous value.
00060 // E.g. the following is equivalent to using mbl_stl_increments
00061 // \return the next value in the sequence.
00062 template<class Out, class Size, class T, class UnOp>
00063 inline T mbl_stl_sequence_n(Out first, Size n, UnOp op, T init)
00064 {
00065   for (; 0 < n; ++first, --n, init = op(init)) *first = init;
00066   return init;
00067 }
00068 
00069 //: Clean out a range of pointers
00070 // NB the dereferenced iterator must be a pointer
00071 template<class iterType>
00072 inline void mbl_stl_clean(iterType first, iterType last)
00073 {
00074    for (; first != last; ++first)
00075    {
00076        delete *first;
00077        *first=0;
00078    }
00079 }
00080 
00081 //: Copy elements in input range for which the supplied predicate is true
00082 //Note bizarely although the STL provides remove_copy if etc etc
00083 //the simple copy_if was dropped fromn the C++ standard
00084 template<typename InputIterator,
00085          typename OutputIterator,
00086          typename Predicate>
00087     inline  OutputIterator mbl_stl_copy_if(InputIterator begin, InputIterator end,
00088                                            OutputIterator destBegin,
00089                                            Predicate pred)
00090 {
00091   while (begin != end)
00092   {
00093     if (pred(*begin))
00094     {
00095       *destBegin++ = *begin; 
00096     }
00097     ++begin;
00098   }
00099   return destBegin;
00100 }
00101 
00102 //----------------------------------------------------------------------------------------------
00103 //Now some map related functors
00104 //
00105 //: select 1st element of a pair (e.g. for map iterators)
00106 //NB something like this is in the SGI extension to the STL but is not included in the standard VCL
00107 //However this is very useful with map iterators so include it here
00108 template <class Pair>
00109 struct mbl_stl_select1st : public vcl_unary_function<Pair, typename Pair::first_type>
00110 {
00111   inline typename Pair::first_type const & operator()(Pair const & pair) const
00112   {
00113     return pair.first;
00114   }
00115 };
00116 
00117 //: select 2nd element of a pair (e.g. for map iterators)
00118 //NB something like this is in the SGI extension to the STL but is not included in the standard VCL
00119 //However this is very useful with map iterators so include it here
00120 template <class Pair>
00121 struct mbl_stl_select2nd : public vcl_unary_function<Pair, typename Pair::second_type>
00122 {
00123   inline typename Pair::second_type const & operator()(Pair const & pair) const
00124   {
00125     return pair.second;
00126   }
00127 };
00128 
00129 //Accumulate the second elements of a pair (e.g. for accumulating values through a map)
00130 template <class Pair>
00131 struct mbl_stl_add2nd : public vcl_binary_function<typename Pair::second_type, Pair, typename Pair::second_type>
00132 {
00133   inline typename Pair::second_type  operator()(typename Pair::second_type partSum, Pair const & x2 ) const
00134   {
00135     return partSum + x2.second;
00136   }
00137 };
00138 
00139 
00140 // End of map/pair related functors
00141 //------------------------------------------------------------------------------------
00142 //: Given a vector of things, select an indexed element
00143 //For use in eg STL transform algorithm to extract out required subset of (indexed) objects into a working vector
00144 //e.g. given vector of indices and vector of values, copy out the required subset thus
00145 // \code
00146 // vcl_vector<T> subset
00147 // subset.reserve(indices.size());
00148 // vcl_transform(indices.begin(),indices.end(),
00149 //               vcl_back_inserter(subset),
00150 //               mbl_stl_index_functor(values));
00151 // \endcode
00152 template <class T>
00153 class mbl_stl_index_functor
00154 {
00155   //This functor copies out  element vec[index]
00156   //For use in eg STL transform algorithm to extract out required subset of (indexed) points into a working vector
00157   //No bounds checking is done
00158  private:
00159   //:const reference to vector used to store the objects indexed
00160   const vcl_vector<T >& vec_;
00161 
00162  public:
00163   mbl_stl_index_functor(const vcl_vector<T >& vec): vec_(vec) {}
00164   inline const T& operator()(unsigned index) const { return vec_[index]; }
00165 };
00166 
00167 
00168 //------------------------------------------------------------------------------------
00169 //: implementation class for use with mbl_stl_output
00170 template <class Cont>
00171 class mbl_stl_output_t1
00172 {
00173  public:
00174   const Cont &c;
00175   const char *sep;
00176   mbl_stl_output_t1(const Cont& c, const char * sep): c(c), sep(sep) {}
00177 };
00178 
00179 //: implementation function for use with mbl_stl_output
00180 template <class Cont> inline 
00181 vcl_ostream& operator<<(vcl_ostream& s, const mbl_stl_output_t1<Cont>& t)
00182 {
00183   if (t.c.empty()) return s;
00184   VCL_DISAPPEARING_TYPENAME Cont::const_iterator it=t.c.begin(), end=t.c.end();
00185   s << *it;
00186   ++it;
00187   for (; it!=end; ++it)
00188     s << t.sep << *it;
00189   return s;
00190 }
00191 
00192 //: Allow easy stream output of STL container contents.
00193 // \verbatim
00194 // vcl_vector<int> c;
00195 // ...
00196 // vcl_cout << "The contents of c using normal << notation" <<
00197 //   mbl_stl_output(c) << vcl_endl;
00198 // \endverbatim
00199 template <class Cont> inline
00200 mbl_stl_output_t1<Cont> mbl_stl_output(const Cont &c, const char * sep=" ")
00201 {
00202   return mbl_stl_output_t1<Cont>(c, sep);
00203 }
00204 
00205 #endif // mbl_stl_h_