1 /* 2 * Copyright (c) 1999-2000, Eric Moon. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions, and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 // functional_tools.h 33 // 34 // PURPOSE 35 // Some extra STL-related functors, adaptors, & helper functions. 36 // 37 // NOTES 38 // bound_method() makes it easy to use STL algorithms to apply a given 39 // method in a given object to a set of instances of another class. 40 // 41 // The additional-argument functors aren't perfected; most notably, 42 // bind2nd() doesn't handle bound methods that take objects by 43 // reference. +++++ 44 // 45 // HISTORY 46 // e.moon 27jul99 begun 47 48 #ifndef __functional_tools_H__ 49 #define __functional_tools_H__ 50 51 #include "cortex_defs.h" 52 __BEGIN_CORTEX_NAMESPACE 53 54 /////////////////////////////////////////////////////////////////////////// 55 // bound_method 56 /////////////////////////////////////////////////////////////////////////// 57 58 // ***** no additional arguments ***** 59 60 // 27jul99: functor adaptor "call a given method of a given object with argument" 61 template<class _retT, class _subjectT, class _objectT> 62 class bound_method_t { 63 public: 64 explicit bound_method_t( 65 // the bound instance on which the method will be called 66 _subjectT& __subject, 67 // the method 68 _retT (_subjectT::* __method)(_objectT*)) : _m_subject(__subject), _m_method(__method) {} 69 70 _retT operator()(_objectT* o) const { 71 return (_m_subject.*_m_method)(o); 72 } 73 74 private: 75 _subjectT& _m_subject; 76 _retT (_subjectT::* _m_method)(_objectT*); 77 }; 78 79 // 27jul99: functor adaptor "call a given method of a given object with argument" 80 template<class _retT, class _subjectT, class _objectT> 81 class bound_const_method_t { 82 public: 83 explicit bound_const_method_t( 84 // the bound instance on which the method will be called 85 _subjectT& __subject, 86 // the method 87 _retT (_subjectT::* __method)(const _objectT*)) : _m_subject(__subject), _m_method(__method) {} 88 89 _retT operator()(const _objectT* o) const { 90 return (_m_subject.*_m_method)(o); 91 } 92 93 private: 94 _subjectT& _m_subject; 95 _retT (_subjectT::* _m_method)(const _objectT*); 96 }; 97 98 template<class _retT, class _subjectT, class _objectT> 99 class bound_method_ref_t { 100 public: 101 explicit bound_method_ref_t( 102 // the bound instance on which the method will be called 103 _subjectT& __subject, 104 // the method 105 _retT (_subjectT::* __method)(_objectT&)) : _m_subject(__subject), _m_method(__method) {} 106 107 _retT operator()(_objectT& o) const { 108 return (_m_subject.*_m_method)(o); 109 } 110 111 private: 112 _subjectT& _m_subject; 113 _retT (_subjectT::* _m_method)(_objectT&); 114 }; 115 116 template<class _retT, class _subjectT, class _objectT> 117 class bound_const_method_ref_t { 118 public: 119 explicit bound_const_method_ref_t( 120 // the bound instance on which the method will be called 121 _subjectT& __subject, 122 // the method 123 _retT (_subjectT::* __method)(const _objectT&)) : _m_subject(__subject), _m_method(__method) {} 124 125 _retT operator()(const _objectT& o) const { 126 return (_m_subject.*_m_method)(o); 127 } 128 129 private: 130 _subjectT& _m_subject; 131 _retT (_subjectT::* _m_method)(const _objectT&); 132 }; 133 134 // ***** 1 additional argument ***** 135 136 // 27jul99: functor adaptor "call a given method of a given object with argument" 137 // + an additional argument 138 template<class _retT, class _subjectT, class _objectT, class _arg1T> 139 class bound_method1_t { 140 public: 141 explicit bound_method1_t( 142 // the bound instance on which the method will be called 143 _subjectT& __subject, 144 // the method 145 _retT (_subjectT::* __method)(_objectT*, _arg1T)) : _m_subject(__subject), _m_method(__method) {} 146 147 _retT operator()(_objectT* o, _arg1T arg1) const { 148 return (_m_subject.*_m_method)(o, arg1); 149 } 150 151 private: 152 _subjectT& _m_subject; 153 _retT (_subjectT::* _m_method)(_objectT*, _arg1T); 154 }; 155 156 157 // 27jul99: functor adaptor "call a given method of a given object with argument" 158 template<class _retT, class _subjectT, class _objectT, class _arg1T> 159 class bound_const_method1_t { 160 public: 161 explicit bound_const_method1_t( 162 // the bound instance on which the method will be called 163 _subjectT& __subject, 164 // the method 165 _retT (_subjectT::* __method)(const _objectT*, _arg1T)) : _m_subject(__subject), _m_method(__method) {} 166 167 _retT operator()(const _objectT* o, _arg1T arg1) const{ 168 return (_m_subject.*_m_method)(o, arg1); 169 } 170 171 private: 172 _subjectT& _m_subject; 173 _retT (_subjectT::* _m_method)(const _objectT*,_arg1T); 174 }; 175 176 template<class _retT, class _subjectT, class _objectT, class _arg1T> 177 class bound_method_ref1_t { 178 public: 179 explicit bound_method_ref1_t( 180 // the bound instance on which the method will be called 181 _subjectT& __subject, 182 // the method 183 _retT (_subjectT::* __method)(_objectT&,_arg1T)) : _m_subject(__subject), _m_method(__method) {} 184 185 _retT operator()(_objectT& o, _arg1T arg1) const { 186 return (_m_subject.*_m_method)(o, arg1); 187 } 188 189 private: 190 _subjectT& _m_subject; 191 _retT (_subjectT::* _m_method)(_objectT&,_arg1T); 192 }; 193 194 template<class _retT, class _subjectT, class _objectT, class _arg1T> 195 class bound_const_method_ref1_t { 196 public: 197 explicit bound_const_method_ref1_t( 198 // the bound instance on which the method will be called 199 _subjectT& __subject, 200 // the method 201 _retT (_subjectT::* __method)(const _objectT&,_arg1T)) : _m_subject(__subject), _m_method(__method) {} 202 203 _retT operator()(const _objectT& o, _arg1T arg1) const { 204 return (_m_subject.*_m_method)(o, arg1); 205 } 206 207 private: 208 _subjectT& _m_subject; 209 _retT (_subjectT::* _m_method)(const _objectT&,_arg1T); 210 }; 211 212 213 // 27jul99: adaptor functions 214 215 // ***** 0-argument ***** 216 217 template<class _retT, class _subjectT, class _objectT> 218 inline bound_method_t<_retT,_subjectT,_objectT> bound_method( 219 _subjectT& subject, _retT (_subjectT::* method)(_objectT*)) { 220 return bound_method_t<_retT,_subjectT,_objectT>(subject, method); 221 } 222 223 template<class _retT, class _subjectT, class _objectT> 224 inline bound_const_method_t<_retT,_subjectT,_objectT> bound_method( 225 _subjectT& subject, _retT (_subjectT::* method)(const _objectT*)) { 226 return bound_const_method_t<_retT,_subjectT,_objectT>(subject, method); 227 } 228 229 template<class _retT, class _subjectT, class _objectT> 230 inline bound_method_ref_t<_retT,_subjectT,_objectT> bound_method( 231 _subjectT& subject, _retT (_subjectT::* method)(_objectT&)) { 232 return bound_method_ref_t<_retT,_subjectT,_objectT>(subject, method); 233 } 234 235 template<class _retT, class _subjectT, class _objectT> 236 inline bound_const_method_ref_t<_retT,_subjectT,_objectT> bound_method( 237 _subjectT& subject, _retT (_subjectT::* method)(const _objectT&)) { 238 return bound_const_method_ref_t<_retT,_subjectT,_objectT>(subject, method); 239 } 240 241 // ***** 1-argument ***** 242 243 template<class _retT, class _subjectT, class _objectT, class _arg1T> 244 inline bound_method1_t<_retT,_subjectT,_objectT,_arg1T> bound_method( 245 _subjectT& subject, _retT (_subjectT::* method)(_objectT*,_arg1T)) { 246 return bound_method1_t<_retT,_subjectT,_objectT,_arg1T>(subject, method); 247 } 248 249 template<class _retT, class _subjectT, class _objectT, class _arg1T> 250 inline bound_const_method1_t<_retT,_subjectT,_objectT,_arg1T> bound_method( 251 _subjectT& subject, _retT (_subjectT::* method)(const _objectT*,_arg1T)) { 252 return bound_const_method1_t<_retT,_subjectT,_objectT,_arg1T>(subject, method); 253 } 254 255 template<class _retT, class _subjectT, class _objectT, class _arg1T> 256 inline bound_method_ref1_t<_retT,_subjectT,_objectT,_arg1T> bound_method( 257 _subjectT& subject, _retT (_subjectT::* method)(_objectT&,_arg1T)) { 258 return bound_method_ref1_t<_retT,_subjectT,_objectT,_arg1T>(subject, method); 259 } 260 261 template<class _retT, class _subjectT, class _objectT, class _arg1T> 262 inline bound_const_method_ref1_t<_retT,_subjectT,_objectT,_arg1T> bound_method( 263 _subjectT& subject, _retT (_subjectT::* method)(const _objectT&,_arg1T)) { 264 return bound_const_method_ref1_t<_retT,_subjectT,_objectT,_arg1T>(subject, method); 265 } 266 267 __END_CORTEX_NAMESPACE 268 #endif /*__functional_tools_H__*/ 269