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" 61template<class _retT, class _subjectT, class _objectT> 62class bound_method_t { 63public: 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 74private: 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" 80template<class _retT, class _subjectT, class _objectT> 81class bound_const_method_t { 82public: 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 93private: 94 _subjectT& _m_subject; 95 _retT (_subjectT::* _m_method)(const _objectT*); 96}; 97 98template<class _retT, class _subjectT, class _objectT> 99class bound_method_ref_t { 100public: 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 111private: 112 _subjectT& _m_subject; 113 _retT (_subjectT::* _m_method)(_objectT&); 114}; 115 116template<class _retT, class _subjectT, class _objectT> 117class bound_const_method_ref_t { 118public: 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 129private: 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 138template<class _retT, class _subjectT, class _objectT, class _arg1T> 139class bound_method1_t { 140public: 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 151private: 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" 158template<class _retT, class _subjectT, class _objectT, class _arg1T> 159class bound_const_method1_t { 160public: 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 171private: 172 _subjectT& _m_subject; 173 _retT (_subjectT::* _m_method)(const _objectT*,_arg1T); 174}; 175 176template<class _retT, class _subjectT, class _objectT, class _arg1T> 177class bound_method_ref1_t { 178public: 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 189private: 190 _subjectT& _m_subject; 191 _retT (_subjectT::* _m_method)(_objectT&,_arg1T); 192}; 193 194template<class _retT, class _subjectT, class _objectT, class _arg1T> 195class bound_const_method_ref1_t { 196public: 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 207private: 208 _subjectT& _m_subject; 209 _retT (_subjectT::* _m_method)(const _objectT&,_arg1T); 210}; 211 212 213// 27jul99: adaptor functions 214 215// ***** 0-argument ***** 216 217template<class _retT, class _subjectT, class _objectT> 218inline 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 223template<class _retT, class _subjectT, class _objectT> 224inline 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 229template<class _retT, class _subjectT, class _objectT> 230inline 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 235template<class _retT, class _subjectT, class _objectT> 236inline 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 243template<class _retT, class _subjectT, class _objectT, class _arg1T> 244inline 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 249template<class _retT, class _subjectT, class _objectT, class _arg1T> 250inline 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 255template<class _retT, class _subjectT, class _objectT, class _arg1T> 256inline 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 261template<class _retT, class _subjectT, class _objectT, class _arg1T> 262inline 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