2009-06-20 01:28:47 +02:00
|
|
|
|
/*
|
|
|
|
|
|
FunctionClosure(Test) - appending, mixing and filtering typelists
|
2010-12-17 23:28:49 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
Copyright (C)
|
|
|
|
|
|
2009, Hermann Vosseler <Ichthyostega@web.de>
|
2010-12-17 23:28:49 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
**Lumiera** is free software; you can redistribute it and/or modify it
|
|
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
|
|
Free Software Foundation; either version 2 of the License, or (at your
|
|
|
|
|
|
option) any later version. See the file COPYING for further details.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
* *****************************************************************/
|
2009-06-20 01:28:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @file function-closure-test.cpp
|
2018-01-12 03:03:25 +01:00
|
|
|
|
** Testing a combination of std::function objects and metaprogramming.
|
2009-06-21 08:38:24 +02:00
|
|
|
|
** Argument types will be extracted and represented as typelist, so they
|
2012-01-07 00:02:03 +01:00
|
|
|
|
** can be manipulated at compile time. This test uses some test functions
|
2009-06-21 08:38:24 +02:00
|
|
|
|
** and systematically applies or binds them to corresponding data tuples.
|
|
|
|
|
|
** Moreover, closure objects will be constructed in various flavours,
|
|
|
|
|
|
** combining a function object and a set of parameters.
|
2009-06-20 04:43:52 +02:00
|
|
|
|
**
|
2009-06-20 01:28:47 +02:00
|
|
|
|
** @see function-closure.hpp
|
|
|
|
|
|
** @see control::CmdClosure real world usage example
|
|
|
|
|
|
**
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/test/run.hpp"
|
2009-06-21 02:51:37 +02:00
|
|
|
|
#include "lib/test/test-helper.hpp"
|
|
|
|
|
|
#include "lib/meta/typelist.hpp"
|
2011-09-25 15:40:16 +02:00
|
|
|
|
#include "lib/meta/typelist-manip.hpp"
|
2009-06-21 02:51:37 +02:00
|
|
|
|
#include "lib/meta/function.hpp"
|
2009-06-20 01:28:47 +02:00
|
|
|
|
#include "lib/meta/function-closure.hpp"
|
2009-06-20 18:41:18 +02:00
|
|
|
|
#include "meta/typelist-diagnostics.hpp"
|
2009-06-20 23:39:45 +02:00
|
|
|
|
#include "meta/tuple-diagnostics.hpp"
|
2009-06-20 01:28:47 +02:00
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
|
|
using ::test::Test;
|
|
|
|
|
|
using std::string;
|
|
|
|
|
|
using std::cout;
|
2009-06-21 02:51:37 +02:00
|
|
|
|
using std::endl;
|
2009-06-20 01:28:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
2011-12-03 02:56:50 +01:00
|
|
|
|
namespace lib {
|
|
|
|
|
|
namespace meta {
|
|
|
|
|
|
namespace test {
|
2009-06-20 18:41:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace { // test data
|
|
|
|
|
|
|
2025-06-05 19:11:46 +02:00
|
|
|
|
using List1 = TySeq<Num<1>, Num<2>, Num<3> >::List;
|
|
|
|
|
|
using List2 = TySeq<Num<5>, Num<6>, Num<7> >::List;
|
2009-06-20 18:41:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** special test fun
|
|
|
|
|
|
* accepting the terrific Num types */
|
|
|
|
|
|
template<char i,char ii, char iii>
|
|
|
|
|
|
int
|
|
|
|
|
|
getNumberz (Num<i> one, Num<ii> two, Num<iii> three)
|
|
|
|
|
|
{
|
|
|
|
|
|
return one.o_ + two.o_ + three.o_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2009-06-21 08:38:24 +02:00
|
|
|
|
|
|
|
|
|
|
int fun0 () { return -1; }
|
|
|
|
|
|
int fun1 (int i1) { return i1; }
|
|
|
|
|
|
int fun2 (int i1, int i2) { return i1+i2; }
|
|
|
|
|
|
int fun3 (int i1, int i2, int i3) { return i1+i2+i3; }
|
|
|
|
|
|
|
2009-06-20 18:41:18 +02:00
|
|
|
|
} // (End) test data
|
2009-07-03 14:31:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-06-05 03:19:03 +02:00
|
|
|
|
using func::bindArgTuple;
|
2009-07-03 14:31:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
2013-10-24 23:06:36 +02:00
|
|
|
|
/*********************************************************************//**
|
2009-06-21 08:38:24 +02:00
|
|
|
|
* @test building a function closure for a given function or functor,
|
|
|
|
|
|
* while arguments are passed in as tuple
|
2009-06-21 02:51:37 +02:00
|
|
|
|
* - accessing signatures as typelists
|
|
|
|
|
|
* - bind free function to tuple
|
|
|
|
|
|
* - bind functor to tuple
|
2025-06-04 01:49:07 +02:00
|
|
|
|
* @remark this test is _rather low-level_ and documents the construction
|
2025-06-05 19:11:46 +02:00
|
|
|
|
* of the implementation; furthermore, most of this construction
|
|
|
|
|
|
* was obsoleted by newer language features, notably std::apply
|
|
|
|
|
|
* and the technique to unpack variadic-λ arguments.
|
|
|
|
|
|
* What remains, is now largely a definition how to handle
|
|
|
|
|
|
* function argument list signatures, to build suitable
|
|
|
|
|
|
* argument tuple types by metaprogramming, and finally
|
|
|
|
|
|
* to pass them to construct a binder.
|
|
|
|
|
|
* @see function-composition-test.cpp (advanced features like partial application)
|
2009-06-20 01:28:47 +02:00
|
|
|
|
*/
|
|
|
|
|
|
class FunctionClosure_test : public Test
|
|
|
|
|
|
{
|
2009-06-20 04:43:52 +02:00
|
|
|
|
virtual void
|
|
|
|
|
|
run (Arg)
|
2009-06-20 01:28:47 +02:00
|
|
|
|
{
|
2025-06-04 01:49:07 +02:00
|
|
|
|
verify_setup();
|
|
|
|
|
|
check_signatureTypeManip();
|
|
|
|
|
|
check_bindFree();
|
|
|
|
|
|
check_bindFunc();
|
2009-06-20 01:28:47 +02:00
|
|
|
|
}
|
2009-06-20 18:41:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** verify the test input data
|
2025-06-04 01:49:07 +02:00
|
|
|
|
* @see TypeListManipl_test#check_diagnostics() for
|
|
|
|
|
|
* explanation of the DISPLAY and EXPECT macros.
|
2009-06-20 18:41:18 +02:00
|
|
|
|
*/
|
|
|
|
|
|
void
|
2025-06-04 01:49:07 +02:00
|
|
|
|
verify_setup()
|
2009-06-20 18:41:18 +02:00
|
|
|
|
{
|
|
|
|
|
|
DISPLAY (List1);
|
|
|
|
|
|
DISPLAY (List2);
|
|
|
|
|
|
;
|
2010-12-10 02:55:40 +01:00
|
|
|
|
CHECK (6 == (getNumberz<1,2,3> (Num<1>(), Num<2>(), Num<3>())));
|
|
|
|
|
|
CHECK (6 == (getNumberz<1,1,1> (Num<1>(), Num<1>(2), Num<1>(3))));
|
2009-06-20 18:41:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2009-06-21 02:51:37 +02:00
|
|
|
|
check_signatureTypeManip ()
|
|
|
|
|
|
{
|
|
|
|
|
|
typedef int someFunc(Num<5>,Num<9>);
|
2017-03-19 02:48:32 +01:00
|
|
|
|
typedef _Fun<someFunc>::Ret RetType; // should be int
|
|
|
|
|
|
typedef _Fun<someFunc>::Args Args;
|
2009-06-21 02:51:37 +02:00
|
|
|
|
DISPLAY (Args);
|
|
|
|
|
|
|
2009-06-30 04:54:50 +02:00
|
|
|
|
typedef Prepend<Num<1>, Args>::Seq NewArgs; // manipulate the argument type(s)
|
2009-06-21 02:51:37 +02:00
|
|
|
|
DISPLAY (NewArgs);
|
|
|
|
|
|
|
2023-11-22 22:11:59 +01:00
|
|
|
|
typedef BuildFunType<RetType,NewArgs>::Sig NewSig; // re-build a new function signature
|
2009-06-21 02:51:37 +02:00
|
|
|
|
|
|
|
|
|
|
NewSig& fun = getNumberz<1,5,9>; //...which is compatible to an existing real function signature!
|
|
|
|
|
|
|
2010-12-10 02:55:40 +01:00
|
|
|
|
CHECK (1+5+9 == fun(Num<1>(), Num<5>(), Num<9>()));
|
2009-06-21 02:51:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
check_bindFree ()
|
|
|
|
|
|
{
|
2009-06-21 08:38:24 +02:00
|
|
|
|
cout << "\t:\n\t: ---Bind----\n";
|
|
|
|
|
|
|
2025-06-04 01:49:07 +02:00
|
|
|
|
Tuple<TySeq<>> tup0 ;
|
|
|
|
|
|
Tuple<TySeq<int>> tup1 (11);
|
|
|
|
|
|
Tuple<TySeq<int,int>> tup2 (11,12);
|
|
|
|
|
|
Tuple<TySeq<int,int,int>> tup3 (11,12,13);
|
2025-06-05 03:19:03 +02:00
|
|
|
|
DUMPVAL (tup0);
|
|
|
|
|
|
DUMPVAL (tup1);
|
|
|
|
|
|
DUMPVAL (tup2);
|
|
|
|
|
|
DUMPVAL (tup3);
|
2009-06-21 08:38:24 +02:00
|
|
|
|
|
2025-06-05 19:11:46 +02:00
|
|
|
|
using BoundFun = function<int()>;
|
2009-06-21 08:38:24 +02:00
|
|
|
|
|
2025-06-05 19:11:46 +02:00
|
|
|
|
BoundFun functor0 = bindArgTuple (fun0, tup0);
|
|
|
|
|
|
BoundFun functor1 = bindArgTuple (fun1, tup1);
|
|
|
|
|
|
BoundFun functor2 = bindArgTuple (fun2, tup2);
|
|
|
|
|
|
BoundFun functor3 = bindArgTuple (fun3, tup3);
|
2009-06-21 08:38:24 +02:00
|
|
|
|
|
2010-12-10 02:55:40 +01:00
|
|
|
|
CHECK (-1 == functor0() );
|
|
|
|
|
|
CHECK (11 == functor1() );
|
|
|
|
|
|
CHECK (11+12 == functor2() );
|
|
|
|
|
|
CHECK (11+12+13 == functor3() );
|
2009-06-21 08:38:24 +02:00
|
|
|
|
|
2009-06-21 02:51:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
check_bindFunc ()
|
|
|
|
|
|
{
|
2025-06-04 01:49:07 +02:00
|
|
|
|
Tuple<TySeq<>> tup0 ;
|
|
|
|
|
|
Tuple<TySeq<int>> tup1 (11);
|
|
|
|
|
|
Tuple<TySeq<int,int>> tup2 (11,12);
|
|
|
|
|
|
Tuple<TySeq<int,int,int>> tup3 (11,12,13);
|
2009-06-21 08:38:24 +02:00
|
|
|
|
function<int()> unbound_functor0 (fun0);
|
|
|
|
|
|
function<int(int)> unbound_functor1 (fun1);
|
|
|
|
|
|
function<int(int,int)> unbound_functor2 (fun2);
|
|
|
|
|
|
function<int(int,int,int)> unbound_functor3 (fun3);
|
|
|
|
|
|
|
2025-06-05 19:11:46 +02:00
|
|
|
|
using BoundFun = function<int()>;
|
2009-06-21 08:38:24 +02:00
|
|
|
|
|
2025-06-05 19:11:46 +02:00
|
|
|
|
BoundFun functor0 = bindArgTuple (unbound_functor0, tup0);
|
|
|
|
|
|
BoundFun functor1 = bindArgTuple (unbound_functor1, tup1);
|
|
|
|
|
|
BoundFun functor2 = bindArgTuple (unbound_functor2, tup2);
|
|
|
|
|
|
BoundFun functor3 = bindArgTuple (unbound_functor3, tup3);
|
2009-06-21 08:38:24 +02:00
|
|
|
|
|
2010-12-10 02:55:40 +01:00
|
|
|
|
CHECK (-1 == functor0() );
|
|
|
|
|
|
CHECK (11 == functor1() );
|
|
|
|
|
|
CHECK (11+12 == functor2() );
|
|
|
|
|
|
CHECK (11+12+13 == functor3() );
|
2009-06-21 08:38:24 +02:00
|
|
|
|
|
2009-06-20 18:41:18 +02:00
|
|
|
|
}
|
2009-06-20 01:28:47 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Register this test class... */
|
|
|
|
|
|
LAUNCHER (FunctionClosure_test, "unit common");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-12-03 02:56:50 +01:00
|
|
|
|
}}} // namespace lib::meta::test
|