lumiera_/tests/library/meta/function-closure-test.cpp

205 lines
6.6 KiB
C++
Raw Normal View History

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
** Testing a combination of std::function objects and metaprogramming.
** 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
** 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 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"
#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"
#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
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_;
}
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
using func::bindArgTuple;
/*********************************************************************//**
* @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
* @remark this test is _rather low-level_ and documents the construction
* 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
{
virtual void
run (Arg)
2009-06-20 01:28:47 +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
* @see TypeListManipl_test#check_diagnostics() for
* explanation of the DISPLAY and EXPECT macros.
2009-06-20 18:41:18 +02:00
*/
void
verify_setup()
2009-06-20 18:41:18 +02:00
{
DISPLAY (List1);
DISPLAY (List2);
;
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>);
typedef _Fun<someFunc>::Ret RetType; // should be int
typedef _Fun<someFunc>::Args Args;
2009-06-21 02:51:37 +02:00
DISPLAY (Args);
typedef Prepend<Num<1>, Args>::Seq NewArgs; // manipulate the argument type(s)
2009-06-21 02:51:37 +02:00
DISPLAY (NewArgs);
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!
CHECK (1+5+9 == fun(Num<1>(), Num<5>(), Num<9>()));
2009-06-21 02:51:37 +02:00
}
void
check_bindFree ()
{
cout << "\t:\n\t: ---Bind----\n";
Tuple<TySeq<>> tup0 ;
Tuple<TySeq<int>> tup1 (11);
Tuple<TySeq<int,int>> tup2 (11,12);
Tuple<TySeq<int,int,int>> tup3 (11,12,13);
DUMPVAL (tup0);
DUMPVAL (tup1);
DUMPVAL (tup2);
DUMPVAL (tup3);
using BoundFun = function<int()>;
BoundFun functor0 = bindArgTuple (fun0, tup0);
BoundFun functor1 = bindArgTuple (fun1, tup1);
BoundFun functor2 = bindArgTuple (fun2, tup2);
BoundFun functor3 = bindArgTuple (fun3, tup3);
CHECK (-1 == functor0() );
CHECK (11 == functor1() );
CHECK (11+12 == functor2() );
CHECK (11+12+13 == functor3() );
2009-06-21 02:51:37 +02:00
}
void
check_bindFunc ()
{
Tuple<TySeq<>> tup0 ;
Tuple<TySeq<int>> tup1 (11);
Tuple<TySeq<int,int>> tup2 (11,12);
Tuple<TySeq<int,int,int>> tup3 (11,12,13);
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);
using BoundFun = function<int()>;
BoundFun functor0 = bindArgTuple (unbound_functor0, tup0);
BoundFun functor1 = bindArgTuple (unbound_functor1, tup1);
BoundFun functor2 = bindArgTuple (unbound_functor2, tup2);
BoundFun functor3 = bindArgTuple (unbound_functor3, tup3);
CHECK (-1 == functor0() );
CHECK (11 == functor1() );
CHECK (11+12 == functor2() );
CHECK (11+12+13 == functor3() );
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