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