1#include <functional>
2#include <memory>
3#include <vector>
4#include <algorithm>
5
6#include "cppunit/cppunit_proxy.h"
7
8#if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
9using namespace std;
10#endif
11
12//
13// TestCase class
14//
15class MemFunPtrTest : public CPPUNIT_NS::TestCase
16{
17  CPPUNIT_TEST_SUITE(MemFunPtrTest);
18  CPPUNIT_TEST(mem_ptr_fun);
19#if defined (STLPORT) && !defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
20  //This test require partial template specialization feature to avoid the
21  //reference to reference problem. No workaround yet for limited compilers.
22  CPPUNIT_IGNORE;
23#endif
24  CPPUNIT_TEST(find);
25  CPPUNIT_TEST_SUITE_END();
26
27protected:
28  // compile test not neccessary to run but...
29  void mem_ptr_fun();
30  void find();
31};
32
33CPPUNIT_TEST_SUITE_REGISTRATION(MemFunPtrTest);
34
35#if defined(_STLP_DONT_RETURN_VOID) && (defined(_STLP_NO_MEMBER_TEMPLATE_CLASSES) && defined(_STLP_NO_CLASS_PARTIAL_SPECIALIZATION))
36#  define _STLP_DONT_TEST_RETURN_VOID
37#endif
38//else there is no workaround for the return void bug
39
40struct S1 { } s1;
41struct S2 { } s2;
42
43int f1(S1&);
44int f2(S1&, S2&);
45int f1c(const S1&);
46int f2c(const S1&, const S2&);
47
48void vf1(S1&);
49void vf2(S1&, S2&);
50void vf1c(const S1&);
51void vf2c(const S1&, const S2&);
52
53class Class {
54public:
55  int f0();
56  int f1(const S1&);
57
58  void vf0();
59  void vf1(const S1&);
60
61  int f0c() const;
62  int f1c(const S1&) const;
63
64  void vf0c() const;
65  void vf1c(const S1&) const;
66};
67
68//
69// tests implementation
70//
71void MemFunPtrTest::mem_ptr_fun()
72{
73  Class obj;
74  const Class& objc = obj;
75
76  // ptr_fun
77
78  ptr_fun(f1)(s1);
79  ptr_fun(f2)(s1, s2);
80
81  ptr_fun(f1c)(s1);
82  ptr_fun(f2c)(s1, s2);
83
84#ifndef _STLP_DONT_TEST_RETURN_VOID
85  ptr_fun(vf1)(s1);
86  ptr_fun(vf2)(s1, s2);
87
88  ptr_fun(vf1c)(s1);
89  ptr_fun(vf2c)(s1, s2);
90#endif /* _STLP_DONT_TEST_RETURN_VOID */
91
92  // mem_fun
93
94  mem_fun(&Class::f0)(&obj);
95  mem_fun(&Class::f1)(&obj, s1);
96
97#ifndef _STLP_DONT_TEST_RETURN_VOID
98  mem_fun(&Class::vf0)(&obj);
99  mem_fun(&Class::vf1)(&obj, s1);
100#endif /* _STLP_DONT_TEST_RETURN_VOID */
101
102  // mem_fun (const)
103
104  mem_fun(&Class::f0c)(&objc);
105  mem_fun(&Class::f1c)(&objc, s1);
106
107#ifndef _STLP_DONT_TEST_RETURN_VOID
108  mem_fun(&Class::vf0c)(&objc);
109  mem_fun(&Class::vf1c)(&objc, s1);
110#endif /* _STLP_DONT_TEST_RETURN_VOID */
111
112  // mem_fun_ref
113
114  mem_fun_ref(&Class::f0)(obj);
115  mem_fun_ref(&Class::f1)(obj, s1);
116
117#ifndef _STLP_DONT_TEST_RETURN_VOID
118  mem_fun_ref(&Class::vf0)(obj);
119  mem_fun_ref(&Class::vf1)(obj, s1);
120#endif /* _STLP_DONT_TEST_RETURN_VOID */
121
122  // mem_fun_ref (const)
123  mem_fun_ref(&Class::f0c)(objc);
124  mem_fun_ref(&Class::f1c)(objc, s1);
125
126#ifndef _STLP_DONT_TEST_RETURN_VOID
127  mem_fun_ref(&Class::vf0c)(objc);
128  mem_fun_ref(&Class::vf1c)(objc, s1);
129#endif /* _STLP_DONT_TEST_RETURN_VOID */
130}
131int f1(S1&)
132{return 1;}
133
134int f2(S1&, S2&)
135{return 2;}
136
137int f1c(const S1&)
138{return 1;}
139
140int f2c(const S1&, const S2&)
141{return 2;}
142
143void vf1(S1&)
144{}
145
146void vf2(S1&, S2&)
147{}
148
149void vf1c(const S1&)
150{}
151
152void vf2c(const S1&, const S2&)
153{}
154
155int Class::f0()
156{return 0;}
157
158int Class::f1(const S1&)
159{return 1;}
160
161void Class::vf0()
162{}
163
164void Class::vf1(const S1&)
165{}
166
167int Class::f0c() const
168{return 0;}
169
170int Class::f1c(const S1&) const
171{return 1;}
172
173void Class::vf0c() const
174{}
175
176void Class::vf1c(const S1&) const
177{}
178
179struct V {
180  public:
181    V(int _v) :
182      v(_v)
183    { }
184
185  bool f( int _v ) const { return (v == _v); }
186
187  int v;
188#if defined (__DMC__)
189  V(){}
190#endif
191};
192
193void MemFunPtrTest::find()
194{
195#if !defined (STLPORT) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
196  vector<V> v;
197
198  v.push_back( V(1) );
199  v.push_back( V(2) );
200  v.push_back( V(3) );
201
202  // step-by-step complication of work for compiler:
203
204  // step 1:
205  const_mem_fun1_ref_t<bool,V,int> pmf = mem_fun_ref( &V::f );
206  binder2nd<const_mem_fun1_ref_t<bool,V,int> > b(pmf, 2);
207  vector<V>::iterator i = find_if( v.begin(), v.end(), b );
208  CPPUNIT_ASSERT(i != v.end());
209  CPPUNIT_ASSERT(i->v == 2);
210
211  // step 2, just check that compiler understand what pass to bind2nd:
212  binder2nd<const_mem_fun1_ref_t<bool,V,int> > b2 = bind2nd( pmf, 2 );
213
214  // step 3, the same as step 1, but more intellect from compiler required:
215  binder2nd<const_mem_fun1_ref_t<bool,V,int> > b3 = bind2nd( mem_fun_ref( &V::f ), 2 );
216
217  vector<V>::iterator j = find_if( v.begin(), v.end(), b3 );
218  CPPUNIT_ASSERT(j != v.end());
219  CPPUNIT_ASSERT(j->v == 2);
220
221  // step 4, more brief, more complex:
222  vector<V>::iterator k = find_if( v.begin(), v.end(), bind2nd( mem_fun_ref( &V::f ), 2 ) );
223  CPPUNIT_ASSERT(k != v.end());
224  CPPUNIT_ASSERT(k->v == 2);
225#endif
226}
227
228#ifdef _STLP_DONT_TEST_RETURN_VOID
229#  undef _STLP_DONT_TEST_RETURN_VOID
230#endif
231