iLab Neuromorphic Robotics Toolkit  0.1
include/nrt/Core/Util/AutoBind.H
Go to the documentation of this file.
00001 /*! @file
00002     @author Edward T. Kaszubski ( ekaszubski@gmail.com )
00003     @copyright GNU Public License (GPL v3)
00004     @section License
00005     @verbatim
00006     // ////////////////////////////////////////////////////////////////////////
00007     //              The iLab Neuromorphic Robotics Toolkit (NRT)             //
00008     // Copyright 2010-2012 by the University of Southern California (USC)    //
00009     //                          and the iLab at USC.                         //
00010     //                                                                       //
00011     //                iLab - University of Southern California               //
00012     //                Hedco Neurociences Building, Room HNB-10               //
00013     //                    Los Angeles, Ca 90089-2520 - USA                   //
00014     //                                                                       //
00015     //      See http://ilab.usc.edu for information about this project.      //
00016     // ////////////////////////////////////////////////////////////////////////
00017     // This file is part of The iLab Neuromorphic Robotics Toolkit.          //
00018     //                                                                       //
00019     // The iLab Neuromorphic Robotics Toolkit is free software: you can      //
00020     // redistribute it and/or modify it under the terms of the GNU General   //
00021     // Public License as published by the Free Software Foundation, either   //
00022     // version 3 of the License, or (at your option) any later version.      //
00023     //                                                                       //
00024     // The iLab Neuromorphic Robotics Toolkit is distributed in the hope     //
00025     // that it will be useful, but WITHOUT ANY WARRANTY; without even the    //
00026     // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR       //
00027     // PURPOSE.  See the GNU General Public License for more details.        //
00028     //                                                                       //
00029     // You should have received a copy of the GNU General Public License     //
00030     // along with The iLab Neuromorphic Robotics Toolkit.  If not, see       //
00031     // <http://www.gnu.org/licenses/>.                                       //
00032     // ////////////////////////////////////////////////////////////////////////
00033     @endverbatim */
00034 
00035 #ifndef INCLUDE_NRT_CORE_UTIL_AUTOBIND_H
00036 #define INCLUDE_NRT_CORE_UTIL_AUTOBIND_H
00037 
00038 #include <functional>
00039 
00040 /* auto_binder inspired by code written by "superbonzo" and "Chris_F" (http://www.codeguru.com/forum/showthread.php?t=512875) */
00041 
00042 #define __AUTO_BIND_FUNCTION_TYPE \
00043         std::function
00044 
00045 namespace details
00046 {
00047 
00048 template<typename... __ArgTypes> struct container{};
00049 
00050 } // details
00051 
00052 namespace details
00053 {
00054 
00055 template<class __FunctionType>
00056 struct funct_types {};
00057 
00058 template<class __ReturnType, class... __ArgTypes>
00059 struct funct_types<__AUTO_BIND_FUNCTION_TYPE<__ReturnType(__ArgTypes...)> >
00060 {
00061     typedef container<__ArgTypes...> _ArgTypesContainer;
00062     typedef __ReturnType _ReturnType;
00063 };
00064 
00065 template<int N>
00066 struct auto_binder
00067 {
00068     template <typename __CallerType, typename __ReturnType, typename... __ArgTypes, typename... __PlaceHolders>
00069     static __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__ArgTypes...)> auto_bind(__ReturnType(__CallerType::*function_ptr)(__ArgTypes...), __CallerType* const caller, __PlaceHolders... placeholders )
00070     {
00071         return auto_binder<N-1>::auto_bind( function_ptr, caller, std::_Placeholder<N>(), placeholders... );
00072     }
00073 
00074     template <typename __ReturnType, typename... __ArgTypes, typename... __PlaceHolders>
00075     static __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__ArgTypes...)> auto_bind(__ReturnType(*function_ptr)(__ArgTypes...), __PlaceHolders... placeholders )
00076     {
00077         return auto_binder<N-1>::auto_bind( function_ptr, std::_Placeholder<N>(), placeholders... );
00078     }
00079 
00080     template <typename... __OutputArgTypes, typename __ReturnType, typename... __InputArgTypes, typename... __Appends>
00081     static __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__OutputArgTypes...)> auto_bind_append( const container<__OutputArgTypes...> & container, const __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__InputArgTypes...)> & function, __Appends... appends )
00082     {
00083         return auto_binder<N-1>::auto_bind_append( container, function, std::_Placeholder<N>(), appends... );
00084     }
00085 };
00086 
00087 template<>
00088 struct auto_binder<0>
00089 {
00090     template <typename __CallerType, typename __ReturnType, typename... __ArgTypes, typename... __PlaceHolders>
00091     static __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__ArgTypes...)> auto_bind(__ReturnType(__CallerType::*function_ptr)(__ArgTypes...), __CallerType* const caller, __PlaceHolders... placeholders )
00092     {
00093         return __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__ArgTypes...)>( std::bind( function_ptr, caller, placeholders... ) );
00094     }
00095 
00096     template <typename __ReturnType, typename... __ArgTypes, typename... __PlaceHolders>
00097     static __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__ArgTypes...)> auto_bind(__ReturnType(*function_ptr)(__ArgTypes...), __PlaceHolders... placeholders )
00098     {
00099         return __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__ArgTypes...)>( std::bind( function_ptr, placeholders... ) );
00100     }
00101 
00102     template <typename... __OutputArgTypes, typename __ReturnType, typename... __InputArgTypes, typename... __Appends>
00103     static __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__OutputArgTypes...)> auto_bind_append( const container<__OutputArgTypes...> & container, const __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__InputArgTypes...)> & function, __Appends... appends )
00104     {
00105         return __AUTO_BIND_FUNCTION_TYPE<__ReturnType( __OutputArgTypes... )>( std::bind( function, appends... ) );
00106     }
00107 };
00108 
00109 } // details
00110 
00111 namespace nrt
00112 {
00113 
00114 template <typename __CallerType, typename __ReturnType, typename... __ArgTypes>
00115 __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__ArgTypes...)> auto_bind(__ReturnType(__CallerType::*function_ptr)(__ArgTypes...), __CallerType* const caller)
00116 {
00117     return details::auto_binder<sizeof...(__ArgTypes)>::auto_bind( function_ptr, caller );
00118 }
00119 
00120 template <typename __ReturnType, typename... __ArgTypes>
00121 __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__ArgTypes...)> auto_bind(__ReturnType(*function_ptr)(__ArgTypes...))
00122 {
00123     return details::auto_binder<sizeof...(__ArgTypes)>::auto_bind( function_ptr );
00124 }
00125 
00126 // this a bit ugly because the compiler was failing to pick up on the output function's args, so now the function type has to be manually specified with __OutputFunctionType and the output args can then be extracted
00127 /* usage:
00128  *  std::auto_bind<__OutputFunctionType>( @input_function, @args_to_append... )
00129  *
00130  * example:
00131  *  typedef std::function<void(int, int, int)> _FunctionType1
00132  *  typedef std::function<void(int, int, int, int)> _FunctionType2
00133  *
00134  *  void some_function( int arg1, int arg2, int arg3, int arg4 ){};
00135  *  const int value_of_arg4 = 5;
00136  *
00137  *  // the usual thing to do is:
00138  *  _FunctionType1 other_function_boost ( boost::bind( &some_function, _1, _2, _3, value_of_arg4 ) );
00139  *  other_function_boost( 4, 5, 6 ); // calls some_function( 4, 5, 6, value_of_arg4 );
00140  *
00141  *  // but now you can do:
00142  *  _FunctionType1 other_function ( std::bind<_FunctionType1>( &some_function, value_of_arg4 ) );
00143  *  other_function( 4, 5, 6 ); // calls some_function( 4, 5, 6, value_of_arg4 );
00144  *
00145  *  // the improvement here is that placeholders are automatically calculated
00146  *  // so if _FunctionType1 had N more arguments, the code for std::bind would remain the same
00147  *  // whereas with boost it would be necessary to specify an additional N placeholders for those arguments
00148  *
00149  *  // the downside is that you can't re-order arguments like you can with boost
00150  *
00151  */
00152 
00153 /*template <typename __OutputFunctionType, typename __ReturnType, typename __CallerType, typename... __InputArgTypes, typename... __Appends>
00154 auto auto_bind( __ReturnType(__CallerType::*function_ptr)(__InputArgTypes...), __CallerType* caller, __Appends... appends ) -> decltype( auto_bind( details::auto_binder<sizeof...(__InputArgTypes)>::auto_bind( function_ptr, caller ), appends... ) )
00155 {
00156     return auto_bind( details::auto_binder<sizeof...(__InputArgTypes)>::auto_bind( function_ptr, caller ), appends... );
00157 }*/
00158 
00159 template <typename __OutputFunctionType, typename __ReturnType, typename... __InputArgTypes, typename... __Appends>
00160 auto auto_bind( const __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__InputArgTypes...)> & function, __Appends... appends ) -> decltype( auto_bind( typename details::funct_types<__OutputFunctionType>::_ArgTypesContainer(), function, appends... ) )
00161 {
00162     // first, we need to find out how many args are in the return function type, since we need a placeholder for each of those args
00163     return auto_bind( typename details::funct_types<__OutputFunctionType>::_ArgTypesContainer(), function, appends... );
00164 }
00165 
00166 // we need to make a placeholder for each item of __OutputArgTypes...
00167 template <typename... __OutputArgTypes, typename __ReturnType, typename... __InputArgTypes, typename... __Appends>
00168 static __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__OutputArgTypes...)> auto_bind( const details::container<__OutputArgTypes...> & container, const __AUTO_BIND_FUNCTION_TYPE<__ReturnType(__InputArgTypes...)> & function, __Appends... appends )
00169 {
00170     return details::auto_binder<sizeof...(__OutputArgTypes)>::auto_bind_append( container, function, appends... );
00171 }
00172 
00173 } // nrt
00174 
00175 #endif // INCLUDE_NRT_CORE_UTIL_AUTOBIND_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines