Orocos Real-Time Toolkit  2.5.0
mystd.hpp
00001 /***************************************************************************
00002   tag: Peter Soetens  Wed Jul 28 09:08:56 CEST 2004  mystd.hpp
00003 
00004                         mystd.hpp -  description
00005                            -------------------
00006     begin                : Wed July 28 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 #ifndef ORO_MYSTD_HPP
00039 #define ORO_MYSTD_HPP
00040 
00041 #include <boost/type_traits/add_reference.hpp>
00042 #include <boost/type_traits/add_const.hpp>
00043 #include <boost/type_traits/is_same.hpp>
00044 #include <boost/type_traits/is_void.hpp>
00045 #include <boost/type_traits/remove_reference.hpp>
00046 #include <boost/type_traits/remove_const.hpp>
00047 #include <boost/mpl/bool.hpp>
00048 #include <boost/mpl/logical.hpp>
00049 #include <boost/utility.hpp>
00050 #include <functional>
00051 #include <algorithm>
00052 #include <vector>
00053 
00054 // here we define some generally useful template stuff that is missing
00055 // from the STL..
00056 namespace RTT { namespace internal {
00057     using namespace boost;
00058 
00059     // combines remove_reference and remove_const
00060     template<typename T>
00061     struct remove_cr
00062     {
00063       typedef typename boost::remove_const<
00064         typename boost::remove_reference<T>::type>::type type;
00065     };
00066 
00067     template<typename T>
00068     struct is_pure_reference
00069     :public boost::mpl::false_
00070     {};
00071 
00072     template<typename T>
00073     struct is_pure_reference<T&>
00074     :public boost::mpl::true_
00075     {};
00076 
00077     template<typename T>
00078     struct is_pure_reference<T const&>
00079     :public boost::mpl::false_
00080     {};
00081 
00082   template<typename iter>
00083   static void delete_all( iter a, iter b )
00084   {
00085     for ( ; a < b; a++ )
00086       delete *a;
00087   };
00088 
00089 
00090     // SGI extension, does not seem present in current GNU STL
00091     // implementation...
00092 
00093     template<typename T>
00094     struct select1st
00095       : public std::unary_function<T, typename T::first_type>
00096     {
00097         typename T::first_type operator()( const T& p ) {
00098             return p.first;
00099         }
00100     };
00101 
00102     template<typename T>
00103     struct select2nd
00104       : public std::unary_function<T, typename T::second_type>
00105     {
00106         typename T::second_type operator()( const T& p ) {
00107             return p.second;
00108         }
00109     };
00110 
00111 #if 0
00112     // Alternative implementations, return const ref.
00113     template<typename PairT>
00114     class select1st
00115       : public std::unary_function<PairT, typename PairT::first_type>
00116     {
00117       typedef typename PairT::first_type ResultT;
00118     public:
00119       const ResultT& operator()( const PairT& p )
00120         {
00121           return p.first;
00122         };
00123     };
00124 
00125     template<typename PairT>
00126     class select2nd
00127       : public std::unary_function<PairT, typename PairT::second_type>
00128     {
00129       typedef typename PairT::second_type ResultT;
00130     public:
00131       const ResultT& operator()( const PairT& p )
00132         {
00133           return p.second;
00134         };
00135     };
00136 #endif
00137 
00138 
00139     // my own handy little extension..
00140     template<typename MapT>
00141     std::vector<typename MapT::mapped_type> values( const MapT& map )
00142     {
00143         std::vector<typename MapT::mapped_type> ret;
00144         ret.reserve( map.size() );
00145         std::transform( map.begin(), map.end(),
00146                         std::back_inserter( ret ),
00147                         select2nd<typename MapT::value_type>() );
00148         return ret;
00149     }
00150 
00151     template<typename MapT>
00152     std::vector<typename MapT::key_type> keys( const MapT& map )
00153     {
00154         std::vector<typename MapT::key_type> ret;
00155         ret.reserve( map.size() );
00156         std::transform( map.begin(), map.end(),
00157                         std::back_inserter( ret ),
00158                         select1st<typename MapT::value_type>() );
00159         return ret;
00160     }
00161     }
00162 }
00163 
00164 namespace std
00165 {
00166     // must be in std namespace.
00167     // STL specialisations for const references : Add others if necessary.
00168     template <class _Tp>
00169     struct equal_to< const _Tp& >
00170         : public binary_function<const _Tp&, const _Tp& ,bool>
00171     {
00172         bool operator()(const _Tp& __x, const _Tp& __y) const { return __x == __y; }
00173     };
00174 
00176     template <class _Tp>
00177     struct not_equal_to<const _Tp&>
00178         : public binary_function<const _Tp&, const _Tp&, bool>
00179     {
00180         bool operator()(const _Tp& __x, const _Tp& __y) const { return __x != __y; }
00181     };
00182 
00184     template <class _Tp>
00185     struct greater<const _Tp&>
00186         : public binary_function<const _Tp&,const _Tp&,bool>
00187     {
00188         bool operator()(const _Tp& __x, const _Tp& __y) const { return __x > __y; }
00189     };
00190 
00192     template <class _Tp>
00193     struct less<const _Tp&>
00194         : public binary_function<const _Tp&,const _Tp&,bool>
00195     {
00196         bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; }
00197     };
00198 
00199     // Ternary functions.
00200     template<class Arg1T, class Arg2T, class Arg3T, class ResultT >
00201     struct ternary_function
00202     {
00203         typedef ResultT result_type;
00204         typedef Arg1T first_argument_type;
00205         typedef Arg2T second_argument_type;
00206         typedef Arg3T third_argument_type;
00207     };
00208 }
00209 
00210 // STL extensions, some are SGI extensions, others are my own..
00211 namespace RTT
00212 {namespace internal {
00213 
00214   template<typename T>
00215   struct identity
00216     : public std::unary_function<T, T>
00217   {
00218     const T& operator()( const T& t ) const
00219       {
00220         return t;
00221       }
00222   };
00223 
00224   // ternary
00225   template<typename ResultT, typename Arg1T, typename Arg2T, typename Arg3T>
00226   struct pointer_to_ternary_function
00227   {
00228       typedef ResultT (Signature)( Arg1T, Arg2T, Arg3T );
00229 
00230       ResultT (*fun)( Arg1T, Arg2T, Arg3T );
00231 
00232     typedef ResultT result_type;
00233     typedef Arg1T first_argument_type;
00234     typedef Arg2T second_argument_type;
00235     typedef Arg3T third_argument_type;
00236     pointer_to_ternary_function( ResultT (*f)(Arg1T, Arg2T, Arg3T ) )
00237       : fun( f )
00238       {
00239       }
00240     ResultT operator()( Arg1T a, Arg2T b, Arg3T c ) const
00241       {
00242         return (*fun)( a, b, c );
00243       }
00244   };
00245 
00246   template<typename ResultT, typename Arg1T, typename Arg2T, typename Arg3T>
00247   pointer_to_ternary_function<ResultT, Arg1T, Arg2T, Arg3T>
00248   ptr_fun( ResultT (*fun)( Arg1T, Arg2T, Arg3T ) )
00249   {
00250     return pointer_to_ternary_function<ResultT, Arg1T, Arg2T, Arg3T>( fun );
00251   }
00252 
00253 
00254   // sixary
00255   template<typename ResultT, typename Arg1T, typename Arg2T, typename Arg3T,
00256            typename Arg4T, typename Arg5T, typename Arg6T >
00257   struct pointer_to_sixary_function
00258   {
00259     typedef ResultT (Signature)( Arg1T, Arg2T, Arg3T, Arg4T, Arg5T, Arg6T );
00260     ResultT (*fun)( Arg1T, Arg2T, Arg3T, Arg4T, Arg5T, Arg6T );
00261     typedef ResultT result_type;
00262     typedef Arg1T first_argument_type;
00263     typedef Arg2T second_argument_type;
00264     typedef Arg3T third_argument_type;
00265     typedef Arg4T fourth_argument_type;
00266     typedef Arg5T fifth_argument_type;
00267     typedef Arg6T sixth_argument_type;
00268     pointer_to_sixary_function( ResultT (*f)(Arg1T, Arg2T, Arg3T, Arg4T, Arg5T, Arg6T ) )
00269       : fun( f )
00270       {
00271       }
00272     ResultT operator()( Arg1T a, Arg2T b, Arg3T c, Arg4T d, Arg5T e, Arg6T f ) const
00273       {
00274         return (*fun)( a, b, c, d, e, f );
00275       }
00276   };
00277 
00278     template<typename ResultT, typename Arg1T, typename Arg2T, typename Arg3T,
00279            typename Arg4T, typename Arg5T, typename Arg6T >
00280   pointer_to_sixary_function<ResultT, Arg1T, Arg2T, Arg3T, Arg4T, Arg5T, Arg6T>
00281   ptr_fun( ResultT (*fun)( Arg1T, Arg2T, Arg3T, Arg4T, Arg5T, Arg6T ) )
00282   {
00283     return pointer_to_sixary_function<ResultT, Arg1T, Arg2T, Arg3T, Arg4T, Arg5T, Arg6T>( fun );
00284   }
00285 
00286 
00287 #if 0
00288 
00289   // the STL lacks a functor multiplying two objects of distinct
00290   // types.. multiplies<T> requires that a and b are both of type
00291   // T when calling operator()(a,b).  So I wrote my own replacement.
00292   // This relies on the GCC typeof C++ extension
00293   template<typename A, typename B>
00294   struct multiplies
00295   {
00296     typedef typeof( A() * B() ) result_type;
00297     typedef A first_argument_type;
00298     typedef B second_argument_type;
00299 
00300     result_type operator()( A a, B b ) const
00301       {
00302         return a*b;
00303       }
00304   };
00305   template<typename A, typename B>
00306   struct divides
00307   {
00308     typedef typeof( A() / B() ) result_type;
00309     typedef A first_argument_type;
00310     typedef B second_argument_type;
00311 
00312     result_type operator()( A a, B b ) const
00313       {
00314         return a/b;
00315       }
00316   };
00317 #else
00318   template<typename R, typename A, typename B>
00319   struct multiplies3
00320   {
00321     typedef R result_type;
00322     typedef A first_argument_type;
00323     typedef B second_argument_type;
00324 
00325     result_type operator()( A a, B b ) const
00326       {
00327         return a*b;
00328       }
00329   };
00330   template<typename R, typename A, typename B>
00331   struct divides3
00332   {
00333     typedef R result_type;
00334     typedef A first_argument_type;
00335     typedef B second_argument_type;
00336 
00337     result_type operator()( A a, B b ) const
00338       {
00339         return a/b;
00340       }
00341   };
00342   template<>
00343   struct divides3<int, int, int>
00344   {
00345     typedef int result_type;
00346     typedef int first_argument_type;
00347     typedef int second_argument_type;
00348 
00349     result_type operator()( int a, int b ) const
00350       {
00351           //integer division by zero will throw a fatal
00352           //exception, aborting the program (SIGFPE). This is
00353           // unacceptable, the problem is however that
00354           // we can not signal an erronous expression in Orocos.
00355           // we propagate zero instead.
00356         return b == 0 ? 0 : a/b;
00357       }
00358   };
00359   template<typename R, typename A, typename B>
00360   struct adds3
00361   {
00362     typedef R result_type;
00363     typedef A first_argument_type;
00364     typedef B second_argument_type;
00365 
00366     result_type operator()( A a, B b ) const
00367       {
00368         return a+b;
00369       }
00370   };
00371   template<typename R, typename A, typename B>
00372   struct subs3
00373   {
00374     typedef R result_type;
00375     typedef A first_argument_type;
00376     typedef B second_argument_type;
00377 
00378     result_type operator()( A a, B b ) const
00379       {
00380         return a-b;
00381       }
00382   };
00383 #endif
00384 }} // namespace RTT
00385 
00386 
00387 
00388 #endif