Lumiera  0.pre.03
»edityourfreedom«
function-closure-test.cpp
Go to the documentation of this file.
1 /*
2  FunctionClosure(Test) - appending, mixing and filtering typelists
3 
4  Copyright (C) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
38 #include "lib/test/run.hpp"
39 #include "lib/test/test-helper.hpp"
40 #include "lib/meta/typelist.hpp"
42 #include "lib/meta/function.hpp"
46 
47 #include <iostream>
48 
49 using ::test::Test;
50 using std::string;
51 using std::cout;
52 using std::endl;
53 
54 
55 namespace lib {
56 namespace meta {
57 namespace test {
58 
59 
60  namespace { // test data
61 
62 
63 
64  typedef Types< Num<1>
65  , Num<2>
66  , Num<3>
67  >::List List1;
68  typedef Types< Num<5>
69  , Num<6>
70  , Num<7>
71  >::List List2;
72 
73 
76  template<char i,char ii, char iii>
77  int
78  getNumberz (Num<i> one, Num<ii> two, Num<iii> three)
79  {
80  return one.o_ + two.o_ + three.o_;
81  }
82 
83 
84  int fun0 () { return -1; }
85  int fun1 (int i1) { return i1; }
86  int fun2 (int i1, int i2) { return i1+i2; }
87  int fun3 (int i1, int i2, int i3) { return i1+i2+i3; }
88 
89  } // (End) test data
90 
91 
92 
93 
94  using func::Apply;
95  using func::TupleApplicator;
96  using func::FunctionClosure;
97  using func::closure;
98  using func::apply;
99 
100 
101  /*********************************************************************/
111  class FunctionClosure_test : public Test
112  {
113  virtual void
114  run (Arg)
115  {
118  check_applyFree ();
119  check_applyFunc ();
120  check_bindFree ();
121  check_bindFunc ();
122  build_closure ();
123  }
124 
125 
130  void
132  {
133  DISPLAY (List1);
134  DISPLAY (List2);
135  ;
136  CHECK (6 == (getNumberz<1,2,3> (Num<1>(), Num<2>(), Num<3>())));
137  CHECK (6 == (getNumberz<1,1,1> (Num<1>(), Num<1>(2), Num<1>(3))));
138  }
139 
140 
141  void
143  {
144  typedef int someFunc(Num<5>,Num<9>);
145  typedef _Fun<someFunc>::Ret RetType; // should be int
146  typedef _Fun<someFunc>::Args Args;
147  DISPLAY (Args);
148 
149  typedef Prepend<Num<1>, Args>::Seq NewArgs; // manipulate the argument type(s)
150  DISPLAY (NewArgs);
151 
152  typedef FunctionTypedef<RetType,NewArgs>::Sig NewSig; // re-build a new function signature
153 
154  NewSig& fun = getNumberz<1,5,9>; //...which is compatible to an existing real function signature!
155 
156  CHECK (1+5+9 == fun(Num<1>(), Num<5>(), Num<9>()));
157  }
158 
159 
160  void
162  {
163  cout << "\t:\n\t: ---Apply---\n";
164 
165  Tuple<Types<>> tup0 ;
166  Tuple<Types<int>> tup1 (11);
167  Tuple<Types<int,int>> tup2 (11,12);
168  Tuple<Types<int,int,int>> tup3 (11,12,13);
169  DUMPVAL (tup0);
170  DUMPVAL (tup1);
171  DUMPVAL (tup2);
172  DUMPVAL (tup3);
173 
174  CHECK (-1 == Apply<0>::invoke<int> (fun0, tup0) );
175  CHECK (11 == Apply<1>::invoke<int> (fun1, tup1) );
176  CHECK (11+12 == Apply<2>::invoke<int> (fun2, tup2) );
177  CHECK (11+12+13 == Apply<3>::invoke<int> (fun3, tup3) );
178 
179  CHECK (-1 == TupleApplicator<int()> (tup0) (fun0) );
180  CHECK (11 == TupleApplicator<int(int)> (tup1) (fun1) );
181  CHECK (11+12 == TupleApplicator<int(int,int)> (tup2) (fun2) );
182  CHECK (11+12+13 == TupleApplicator<int(int,int,int)> (tup3) (fun3) );
183 
184  CHECK (-1 == apply(fun0, tup0) );
185  CHECK (11 == apply(fun1, tup1) );
186  CHECK (11+12 == apply(fun2, tup2) );
187  CHECK (11+12+13 == apply(fun3, tup3) );
188 
189  }
190 
191 
192  void
194  {
195  Tuple<Types<>> tup0 ;
196  Tuple<Types<int>> tup1 (11);
197  Tuple<Types<int,int>> tup2 (11,12);
198  Tuple<Types<int,int,int>> tup3 (11,12,13);
199  function<int()> functor0 (fun0);
200  function<int(int)> functor1 (fun1);
201  function<int(int,int)> functor2 (fun2);
202  function<int(int,int,int)> functor3 (fun3);
203 
204  CHECK (-1 == Apply<0>::invoke<int> (functor0, tup0) );
205  CHECK (11 == Apply<1>::invoke<int> (functor1, tup1) );
206  CHECK (11+12 == Apply<2>::invoke<int> (functor2, tup2) );
207  CHECK (11+12+13 == Apply<3>::invoke<int> (functor3, tup3) );
208 
209  CHECK (-1 == TupleApplicator<int()> (tup0) (functor0) );
210  CHECK (11 == TupleApplicator<int(int)> (tup1) (functor1) );
211  CHECK (11+12 == TupleApplicator<int(int,int)> (tup2) (functor2) );
212  CHECK (11+12+13 == TupleApplicator<int(int,int,int)> (tup3) (functor3) );
213 
214  CHECK (-1 == apply(functor0, tup0) );
215  CHECK (11 == apply(functor1, tup1) );
216  CHECK (11+12 == apply(functor2, tup2) );
217  CHECK (11+12+13 == apply(functor3, tup3) );
218 
219  }
220 
221 
222  void
224  {
225  cout << "\t:\n\t: ---Bind----\n";
226 
227  Tuple<Types<>> tup0 ;
228  Tuple<Types<int>> tup1 (11);
229  Tuple<Types<int,int>> tup2 (11,12);
230  Tuple<Types<int,int,int>> tup3 (11,12,13);
231 
232  typedef function<int()> BoundFun;
233 
234  BoundFun functor0 = Apply<0>::bind<BoundFun> (fun0, tup0);
235  BoundFun functor1 = Apply<1>::bind<BoundFun> (fun1, tup1);
236  BoundFun functor2 = Apply<2>::bind<BoundFun> (fun2, tup3);
237  BoundFun functor3 = Apply<3>::bind<BoundFun> (fun3, tup3);
238 
239  CHECK (-1 == functor0() );
240  CHECK (11 == functor1() );
241  CHECK (11+12 == functor2() );
242  CHECK (11+12+13 == functor3() );
243 
244  functor0 = TupleApplicator<int()> (tup0).bind (fun0);
245  functor1 = TupleApplicator<int(int)> (tup1).bind (fun1);
246  functor2 = TupleApplicator<int(int,int)> (tup2).bind (fun2);
247  functor3 = TupleApplicator<int(int,int,int)> (tup3).bind (fun3);
248 
249  CHECK (-1 == functor0() );
250  CHECK (11 == functor1() );
251  CHECK (11+12 == functor2() );
252  CHECK (11+12+13 == functor3() );
253 
254  }
255 
256 
257  void
259  {
260  Tuple<Types<>> tup0 ;
261  Tuple<Types<int>> tup1 (11);
262  Tuple<Types<int,int>> tup2 (11,12);
263  Tuple<Types<int,int,int>> tup3 (11,12,13);
264  function<int()> unbound_functor0 (fun0);
265  function<int(int)> unbound_functor1 (fun1);
266  function<int(int,int)> unbound_functor2 (fun2);
267  function<int(int,int,int)> unbound_functor3 (fun3);
268 
269  typedef function<int()> BoundFun;
270 
271  BoundFun functor0 = Apply<0>::bind<BoundFun> (unbound_functor0, tup0);
272  BoundFun functor1 = Apply<1>::bind<BoundFun> (unbound_functor1, tup1);
273  BoundFun functor2 = Apply<2>::bind<BoundFun> (unbound_functor2, tup3);
274  BoundFun functor3 = Apply<3>::bind<BoundFun> (unbound_functor3, tup3);
275 
276  CHECK (-1 == functor0() );
277  CHECK (11 == functor1() );
278  CHECK (11+12 == functor2() );
279  CHECK (11+12+13 == functor3() );
280 
281  functor0 = TupleApplicator<int()> (tup0).bind (unbound_functor0);
282  functor1 = TupleApplicator<int(int)> (tup1).bind (unbound_functor1);
283  functor2 = TupleApplicator<int(int,int)> (tup2).bind (unbound_functor2);
284  functor3 = TupleApplicator<int(int,int,int)> (tup3).bind (unbound_functor3);
285 
286  CHECK (-1 == functor0() );
287  CHECK (11 == functor1() );
288  CHECK (11+12 == functor2() );
289  CHECK (11+12+13 == functor3() );
290 
291  }
292 
293 
294  void
296  {
297  Tuple<Types<>> tup0 ;
298  Tuple<Types<int>> tup1 (11);
299  Tuple<Types<int,int>> tup2 (11,12);
300  Tuple<Types<int,int,int>> tup3 (11,12,13);
301 
302  FunctionClosure<int()> clo0 (fun0,tup0);
303  FunctionClosure<int(int)> clo1 (fun1,tup1);
304  FunctionClosure<int(int,int)> clo2 (fun2,tup2);
305  FunctionClosure<int(int,int,int)> clo3 (fun3,tup3);
306 
307  CHECK (-1 == clo0() );
308  CHECK (11 == clo1() );
309  CHECK (11+12 == clo2() );
310  CHECK (11+12+13 == clo3() );
311 
312  function<int()> unbound_functor0 (fun0);
313  function<int(int)> unbound_functor1 (fun1);
314  function<int(int,int)> unbound_functor2 (fun2);
315  function<int(int,int,int)> unbound_functor3 (fun3);
316 
317  clo0 = FunctionClosure<int()> (unbound_functor0,tup0);
318  clo1 = FunctionClosure<int(int)> (unbound_functor1,tup1);
319  clo2 = FunctionClosure<int(int,int)> (unbound_functor2,tup2);
320  clo3 = FunctionClosure<int(int,int,int)> (unbound_functor3,tup3);
321 
322  CHECK (-1 == clo0() );
323  CHECK (11 == clo1() );
324  CHECK (11+12 == clo2() );
325  CHECK (11+12+13 == clo3() );
326 
327  CHECK (-1 == closure(fun0,tup0) () );
328  CHECK (11 == closure(fun1,tup1) () );
329  CHECK (11+12 == closure(fun2,tup2) () );
330  CHECK (11+12+13 == closure(fun3,tup3) () );
331 
332  CHECK (-1 == closure(unbound_functor0,tup0) () );
333  CHECK (11 == closure(unbound_functor1,tup1) () );
334  CHECK (11+12 == closure(unbound_functor2,tup2) () );
335  CHECK (11+12+13 == closure(unbound_functor3,tup3) () );
336 
337 
338  // finally combine all techniques....
339  using NumberzArg = Types<List2>::Seq;
340  using NumberzSig = FunctionTypedef<int,NumberzArg>::Sig;
341 
342  Tuple<NumberzArg> numberzTup (Num<5>(22), Num<6>(33), Num<7>(44));
343 
344  FunctionClosure<NumberzSig> numClo (getNumberz<5,6,7>, numberzTup );
345 
346  CHECK (22+33+44 == numClo() );
347  }
348  };
349 
350 
352  LAUNCHER (FunctionClosure_test, "unit common");
353 
354 
355 
356 }}} // namespace lib::meta::test
A template metaprogramming technique for manipulating collections of types.
Definition: run.hpp:49
LinkedElements< Nummy > List
default case: ownership for heap allocated nodes
Helper for uniform access to function signature types.
Definition: function.hpp:108
Partial function application and building a complete function closure.
void check_diagnostics()
verify the test input data
typename BuildTupleType< TYPES >::Type Tuple
Build a std::tuple from types given as type sequence.
Implementation namespace for support and library code.
LAUNCHER(ConfigFlags_test, "unit common")
Register this test class...
Build function types from given Argument types.
Definition: function.hpp:180
#define DUMPVAL(_IT_)
std::vector< string > & Arg
Definition: run.hpp:54
Metaprogramming tools for transforming functor types.
Simple test class runner.
Helper: prepend a type to an existing type sequence, thus shifting all elements within the sequence t...
Closing a function over its arguments.
A collection of frequently used helper functions to support unit testing.
an extension to typelist-diagnostics.hpp, allowing to dump the contents of a Tuple datatype...
_Fun< SIG >::Ret apply(SIG &f, std::tuple< ARG... > &args)
apply the given function to the argument tuple
Closure-creating template.
_Clo< SIG, Types< ARG... > >::Type closure(SIG &f, std::tuple< ARG... > &args)
close the given function over all arguments, using the values from the argument tuple.
#define DISPLAY(_IT_)
Support for writing metaprogramming unit-tests dealing with typelists and flags.
Metaprogramming: Helpers for manipulating lists-of-types.
constant-wrapper type for debugging purposes, usable for generating lists of distinguishable types ...