|
iLab Neuromorphic Robotics Toolkit
0.1
|
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