diff --git a/src/lib/meta/function-erasure.hpp b/src/lib/meta/function-erasure.hpp new file mode 100644 index 000000000..5f29c783b --- /dev/null +++ b/src/lib/meta/function-erasure.hpp @@ -0,0 +1,214 @@ +/* + FUNCTION-ERASURE.hpp - wrapping a functor object for inline storage while hiding the signature + + Copyright (C) Lumiera.org + 2009, Hermann Vosseler + + This program 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file function-erasure.hpp + ** Partial function application and building a complete function closure. + ** This is a small addendum to (and thin wrapper for) tr1/functional, supporting + ** the case when a function should be closed over (all) arguments, where especially + ** the parameter values to close on are provided as a tuple. + ** + ** @see control::CommandDef usage example + ** @see function.hpp + ** @see tuple.hpp + ** + */ + + +#ifndef LUMIERA_META_FUNCTION_ERASURE_H +#define LUMIERA_META_FUNCTION_ERASURE_H + +#include "lib/meta/typelist.hpp" /////////////TODO +#include "lib/meta/generator.hpp" /////////////TODO +#include "lib/meta/function.hpp" +#include "lib/meta/tuple.hpp" + +#include + +#include "lib/util.hpp" ////////////////////////TODO +#include "lib/error.hpp" + + +namespace lumiera { +namespace typelist{ + + using std::tr1::bind; + //using std::tr1::placeholders::_1; + //using std::tr1::placeholders::_2; + using std::tr1::function; + + + + /** + * Generic wrapper carrying a function object + * while hiding the actual function signature + * @note not statically typesafe. Depending on + * the actual embedded container type, + * it \em might be run-time typesafe. + */ + template + struct FunErasure + : FH + { + template + FunErasure (FUN const& functor) + : FH(functor) + { } + }; + + /** + * Policy for FunErasure: store an embedded tr1::function + * Using this policy allows to store arbitrary complex functor objects + * embedded within a neutral container and retrieving them later type-safe. + * The price to pay is vtable access and heap storage of function arguments. + */ + class StoreFunction + { + /** Helper: type erasure */ + struct Holder + { + enum { SIZE = sizeof(function) }; + char storage_[SIZE]; + virtual ~Holder() {} + }; + + /** embedding the concrete functor object */ + template + struct FunctionHolder : Holder + { + typedef function Functor; + FunctionHolder (SIG& fun) + { + REQUIRE (SIZE >= sizeof(Functor)); + new(&storage_) Functor (fun); + } + ~FunctionHolder() + { + get()->~Functor(); + } + Functor& + get() + { + return static_cast (&storage_); + } + }; + + /** embedded buffer actually holding + * the concrete Functor object */ + Holder holder_; + + public: + template + StoreFunction (SIG& fun) + { + new(&holder_) FunctionHolder (fun); + } + + template + function& + getFun () + { + REQUIRE (INSTANCEOF (FunctionHolder, &holder_)); + return static_cast&> (holder_).get(); + } + }; + + + /** + * Policy for FunErasure: store a bare function pointer. + * Using this policy allows to store a conventional function ptr, + * while still being able to re-access it later with run-time typecheck. + * The price to pay is vtable access. + */ + class StoreFunPtr + { + /** Helper: type erasure */ + struct Holder + { + void *fun_; + virtual ~Holder() {} + }; + + /** storing and retrieving concrete function ptr */ + template + struct FunctionHolder : Holder + { + FunctionHolder (SIG& fun) + { + fun_ = &fun; + } + SIG& + get() + { + return reinterpret_cast (&fun_); + } + }; + + /** embedded container holding the pointer */ + Holder holder_; + + public: + template + StoreFunPtr (SIG& fun) + { + new(&holder_) FunctionHolder (fun); + } + + template + function& + getFun () + { + REQUIRE (INSTANCEOF (FunctionHolder, &holder_)); + return static_cast&> (holder_).get(); + } + }; + + + /** + * Policy for FunErasure: store an unchecked bare function pointer. + * Using this policy allows to store a conventional function ptr, + * and to retrieve it without overhead, but also without safety. + */ + class StoreUncheckedFunPtr + { + void *fun_; + + public: + template + StoreUncheckedFunPtr (SIG& fun) + { + fun_ = &fun; + } + + template + SIG& + getFun () + { + return reinterpret_cast (&fun_); + } + }; + + + + +}} // namespace lumiera::typelist +#endif diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index 323750462..0c8f60501 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -46,10 +46,12 @@ test_lib_SOURCES = \ $(testlib_srcdir)/helloworldtest.cpp \ $(testlib_srcdir)/lifecycletest.cpp \ $(testlib_srcdir)/mainsuite.cpp \ - $(testlib_srcdir)/meta/typelisttest.cpp \ - $(testlib_srcdir)/meta/typelistmaniptest.cpp \ - $(testlib_srcdir)/meta/generatortest.cpp \ - $(testlib_srcdir)/meta/configflagstest.cpp \ + $(testlib_srcdir)/meta/typelist-test.cpp \ + $(testlib_srcdir)/meta/typelist-manip-test.cpp \ + $(testlib_srcdir)/meta/function-closure-test.cpp \ + $(testlib_srcdir)/meta/function-erasure-test.cpp \ + $(testlib_srcdir)/meta/generator-test.cpp \ + $(testlib_srcdir)/meta/config-flags-test.cpp \ $(testlib_srcdir)/query/queryutilstest.cpp \ $(testlib_srcdir)/removefromsettest.cpp \ $(testlib_srcdir)/sanitizedidentifiertest.cpp \ diff --git a/tests/lib/meta/configflagstest.cpp b/tests/lib/meta/config-flags-test.cpp similarity index 98% rename from tests/lib/meta/configflagstest.cpp rename to tests/lib/meta/config-flags-test.cpp index 1098b0385..995ddef56 100644 --- a/tests/lib/meta/configflagstest.cpp +++ b/tests/lib/meta/config-flags-test.cpp @@ -21,7 +21,7 @@ * *****************************************************/ -/** @file configflagstest.cpp +/** @file config-flags-test.cpp ** \par build a type representing a single configuration defined by a set of flags ** ** The semi-automatic assembly of processing node invocation code utilises some @@ -42,7 +42,7 @@ #include "lib/meta/generator.hpp" #include "lib/meta/typelistutil.hpp" #include "lib/meta/configflags.hpp" -#include "meta/typelistdiagnostics.hpp" +#include "meta/typelist-diagnostics.hpp" #include "proc/engine/nodewiringconfig.hpp" #include "lib/util.hpp" @@ -55,8 +55,8 @@ using std::cout; namespace lumiera { - namespace typelist { - namespace test { +namespace typelist{ +namespace test { namespace { // internal definitions @@ -332,8 +332,4 @@ namespace lumiera { - } // namespace test - - } // namespace typelist - -} // namespace lumiera +}}} // namespace lumiera::typelist::test diff --git a/tests/lib/meta/function-closure-test.cpp b/tests/lib/meta/function-closure-test.cpp new file mode 100644 index 000000000..78b205925 --- /dev/null +++ b/tests/lib/meta/function-closure-test.cpp @@ -0,0 +1,90 @@ +/* + FunctionClosure(Test) - appending, mixing and filtering typelists + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +/** @file function-closure-test.cpp + ** bla + ** + ** @see function-closure.hpp + ** @see control::CmdClosure real world usage example + ** + */ + + +#include "lib/test/run.hpp" +#include "lib/meta/function-closure.hpp" +#include "lib/util.hpp" + +//#include +#include + +using ::test::Test; +using std::string; +using std::cout; + + +namespace lumiera { +namespace typelist{ +namespace test { + + + namespace { // test data + + } // (End) test data + + + + + + + /************************************************************************* + * @test ////////////////////////////////////////// + * - building combinations and permutations + */ + class FunctionClosure_test : public Test + { + virtual void run(Arg arg) + { + check_distribute(); + check_combine(); + } + + + void check_distribute() + { + } + + + void check_combine() + { + } + + + }; + + + /** Register this test class... */ + LAUNCHER (FunctionClosure_test, "unit common"); + + + +}}} // namespace lumiera::typelist::test diff --git a/tests/lib/meta/function-erasure-test.cpp b/tests/lib/meta/function-erasure-test.cpp new file mode 100644 index 000000000..c615edbc7 --- /dev/null +++ b/tests/lib/meta/function-erasure-test.cpp @@ -0,0 +1,90 @@ +/* + FunctionErasure(Test) - verify the wrapping of functor object with type erasure + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +/** @file function-erasure-test.cpp + ** bla + ** + ** @see control::FunErasure + ** @see command-mutation.hpp real world usage example + ** + */ + + +#include "lib/test/run.hpp" +#include "lib/meta/function-erasure.hpp" +#include "lib/util.hpp" + +//#include +#include + +using ::test::Test; +using std::string; +using std::cout; + + +namespace lumiera { +namespace typelist{ +namespace test { + + + namespace { // test data + + } // (End) test data + + + + + + + /************************************************************************* + * @test ////////////////////////////////////////// + * - building combinations and permutations + */ + class FunctionErasure_test : public Test + { + virtual void run(Arg arg) + { + check_distribute(); + check_combine(); + } + + + void check_distribute() + { + } + + + void check_combine() + { + } + + + }; + + + /** Register this test class... */ + LAUNCHER (FunctionErasure_test, "unit common"); + + + +}}} // namespace lumiera::typelist::test diff --git a/tests/lib/meta/generatortest.cpp b/tests/lib/meta/generator-test.cpp similarity index 94% rename from tests/lib/meta/generatortest.cpp rename to tests/lib/meta/generator-test.cpp index c4224b4fa..dc7abbcbe 100644 --- a/tests/lib/meta/generatortest.cpp +++ b/tests/lib/meta/generator-test.cpp @@ -21,7 +21,7 @@ * *****************************************************/ -/** @file generatortest.cpp +/** @file generator-test.cpp ** \par what are we doing here?? ** ** the following test composes both an interface and the corresponding implementation @@ -30,7 +30,7 @@ ** in the list. (remember: normally the number and signature of all virtual functions ** need to be absolutely fixed in the class definition) ** - ** @see typelisttest.cpp + ** @see typelist-test.cpp ** @see generator.hpp ** @see lumiera::query::ConfigRules a real world usage example ** @@ -47,12 +47,9 @@ using std::string; using std::cout; -namespace lumiera - { - namespace typelist - { - namespace test - { +namespace lumiera { +namespace typelist{ +namespace test { /** template for generating lots of different test types */ template @@ -89,7 +86,7 @@ namespace lumiera virtual ~DoIt() { cout << "dtor DoIt<"<< X::name << " >\n";} public: void eat (X& x) { cout << x.talk() << "\n";} - using BASE::eat; // prevent shaddowing + using BASE::eat; // prevent shadowing }; typedef Types< Block<1> @@ -148,8 +145,4 @@ namespace lumiera - } // namespace test - - } // namespace typelist - -} // namespace lumiera +}}} // namespace lumiera::typelist::test diff --git a/tests/lib/meta/typelist-diagnostics.hpp b/tests/lib/meta/typelist-diagnostics.hpp new file mode 100644 index 000000000..800af1a39 --- /dev/null +++ b/tests/lib/meta/typelist-diagnostics.hpp @@ -0,0 +1,162 @@ +/* + TYPELIST-DIAGNOSTICS - helper for testing the typelist based utilities + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +/** @file typelist-diagnostics.hpp + ** a Printer template usable for debugging the structure of a typelist built + ** upon some simple debugging-style types. Examples being a Num template, + ** or the Flag type. A Printer type generated from this template provides + ** a static \c print() function returning a string visualising the structure + ** of the typelist provided as parameter to the Printer template. + ** + ** @see typelist-manip-test.cpp + ** @see config-flags-test.cpp + ** + */ +#ifndef META_TYPELIST_DIAGNOSTICS_H +#define META_TYPELIST_DIAGNOSTICS_H + + +#include "lib/meta/generator.hpp" + +#include + +using std::string; +using boost::format; + + +namespace lumiera { +namespace typelist{ + + /** constant-wrapper type for debugging purposes, + * usable for generating lists of distinguishable types + */ + template + struct Num + { + enum{ VAL=I }; + }; + + + /* some forwards used by config-flags-test.cpp */ + template struct Flag; + template< char f1 + , char f2 + , char f3 + , char f4 + , char f5 + > + struct Config; + + + + namespace test { + namespace { // hidden internals + + using boost::format; + + format fmt ("-<%u>%s"); + + struct NullP + { + static string print () { return "-"; } + }; + + /** debugging template, + * printing the "number" used for instantiation on ctor call + */ + template + struct Printer; + + template + struct Printer + : BASE + { + static string print () { return str( fmt % "·" % BASE::print()); } + }; + + template + struct Printer, BASE> ///< display the presence of a Num instance in the typelist + : BASE + { + static string print () { return str( fmt % uint(Num::VAL) % BASE::print()); } + }; + + template + struct Printer, BASE> ///< display the presence of a Flag in the typelist + : BASE + { + static string print () { return str( fmt % uint(Fl) % BASE::print()); } + }; + + + + /** call the debug-print for a typelist + * utilising the Printer template */ + template + string + printSublist () + { + typedef InstantiateChained SubList; + return SubList::print(); + } + + /** Specialisation for debug-printing of a nested sublist */ + template + struct Printer, BASE> + : BASE + { + static string print () + { + typedef Node List; + return string("\n\t+--") + printSublist()+"+" + + BASE::print(); + } + }; + + template + struct Printer, BASE> + : BASE + { + static string print () + { + typedef typename Config::Flags FlagList; + return string("\n\t+-Conf-[") + printSublist()+"]" + + BASE::print(); + } + }; + + +#define DIAGNOSE(LIST) \ + typedef InstantiateChained Contents_##LIST; + +#define DISPLAY(NAME) \ + DIAGNOSE(NAME); cout << STRINGIFY(NAME) << "\t:" << Contents_##NAME::print() << "\n"; + + + + } // (End) internal defs + + + +}}} // namespace lumiera::typelist::test +#endif diff --git a/tests/lib/meta/typelistmaniptest.cpp b/tests/lib/meta/typelist-manip-test.cpp similarity index 96% rename from tests/lib/meta/typelistmaniptest.cpp rename to tests/lib/meta/typelist-manip-test.cpp index 5eb3e0f0e..a9f2ac06a 100644 --- a/tests/lib/meta/typelistmaniptest.cpp +++ b/tests/lib/meta/typelist-manip-test.cpp @@ -21,17 +21,17 @@ * *****************************************************/ -/** @file typelistmaniptest.cpp +/** @file typelist-manip-test.cpp ** \par checking the correct working of simple list manipulation metafunctions ** - ** The semi-automatic assembly of processing node invocation code utilizes some + ** The semi-automatic assembly of processing node invocation code utilises some ** metaprogramming magic built upon simple list manipulation. As template metaprogramming ** is kind-of functional programming, most of this is done by recursion. ** To check the correct working, this test uses some constant-wrapper types and a debugging ** template which will print these constant numbers, thus allowing to verify in the output ** if various lists of such constant-wrapper types were manipulated as expected. ** - ** @see typelisttest.cpp + ** @see typelist-test.cpp ** @see typelistutil.hpp ** @see nodewiringconfig.hpp real world usage example ** @@ -41,7 +41,7 @@ #include "lib/test/run.hpp" #include "lib/meta/generator.hpp" #include "lib/meta/typelistutil.hpp" -#include "meta/typelistdiagnostics.hpp" +#include "meta/typelist-diagnostics.hpp" #include "lib/util.hpp" #include @@ -53,8 +53,8 @@ using std::cout; namespace lumiera { - namespace typelist { - namespace test { +namespace typelist{ +namespace test { namespace { // test data @@ -69,7 +69,7 @@ namespace lumiera { , Num<6> , Num<7> >::List List2; - + template struct CountDown { typedef NullType List; }; template<> struct CountDown > { typedef Node, NullType> List; }; @@ -91,7 +91,7 @@ namespace lumiera { * - append lists, single elements and NullType * in various combinations * - filtering out some types from a typelist by - * using a "predicate template" (metafuction) + * using a "predicate template" (metafunction) * - building combinations and permutations */ class TypeListManipl_test : public Test @@ -224,7 +224,7 @@ namespace lumiera { typedef CombineFlags OnOff; DISPLAY (OnOff); } - + }; @@ -234,8 +234,4 @@ namespace lumiera { - } // namespace test - - } // namespace typelist - -} // namespace lumiera +}}} // namespace lumiera::typelist::test diff --git a/tests/lib/meta/typelisttest.cpp b/tests/lib/meta/typelist-test.cpp similarity index 94% rename from tests/lib/meta/typelisttest.cpp rename to tests/lib/meta/typelist-test.cpp index 20a70cbfb..c31c4a70d 100644 --- a/tests/lib/meta/typelisttest.cpp +++ b/tests/lib/meta/typelist-test.cpp @@ -30,12 +30,9 @@ using std::string; using std::cout; -namespace lumiera - { - namespace typelist - { - namespace test - { +namespace lumiera { +namespace typelist{ +namespace test { template struct Block @@ -46,7 +43,7 @@ namespace lumiera { Zero() { cout << "- The End -"; } }; - + typedef Types< Block<1> , Block<2> @@ -94,8 +91,4 @@ namespace lumiera - } // namespace test - - } // namespace typelist - -} // namespace lumiera +}}} // namespace lumiera::typelist::test diff --git a/tests/lib/meta/typelistdiagnostics.hpp b/tests/lib/meta/typelistdiagnostics.hpp deleted file mode 100644 index 7be9cef31..000000000 --- a/tests/lib/meta/typelistdiagnostics.hpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - TYPELISTDIAGNOSTICS - helper for testing the typelist based utilities - - Copyright (C) Lumiera.org - 2008, Hermann Vosseler - - This program 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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - - -/** @file typelistdiagnostics.hpp - ** a Printer template usable for debugging the structure of a typelist built - ** upon some simple debugging-style types. Examples being a Num template, - ** or the Flag type. A Printer type generated from this template provides - ** a static \c print() function returing a string visualizing the structure - ** of the typelist provided as parameter to the Printer template. - ** - ** @see typelistmaniptest.cpp - ** @see configflagstest.cpp - ** - */ -#ifndef META_TYPELISTDIAGNOSTICS_H -#define META_TYPELISTDIAGNOSTICS_H - - -#include "lib/meta/generator.hpp" - -//#include "lib/meta/typelistutil.hpp" -//#include "lib/meta/util.hpp" -//#include "lib/util.hpp" - -#include - -using std::string; -using boost::format; - - -namespace lumiera { - namespace typelist { - - /** constant-wrapper type for debugging purposes, - * usable for generating lists of distinguishable types - */ - template - struct Num - { - enum{ VAL=I }; - }; - - - /* some forwards used by configflagstest.cpp */ - template struct Flag; - template< char f1 - , char f2 - , char f3 - , char f4 - , char f5 - > - struct Config; - - - - namespace test { - namespace { // internal definitions - - using boost::format; - - format fmt ("-<%u>%s"); - - struct NullP - { - static string print () { return "-"; } - }; - - /** debugging template, - * printing the "number" used for intantiation on ctor call - */ - template - struct Printer; - - template - struct Printer - : BASE - { - static string print () { return str( fmt % "·" % BASE::print()); } - }; - - template - struct Printer, BASE> ///< display the presence of a Num instance in the typelist - : BASE - { - static string print () { return str( fmt % uint(Num::VAL) % BASE::print()); } - }; - - template - struct Printer, BASE> ///< display the presence of a Flag in the typelist - : BASE - { - static string print () { return str( fmt % uint(Fl) % BASE::print()); } - }; - - - - /** call the debug-print for a typelist - * utilizing the Printer template */ - template - string - printSublist () - { - typedef InstantiateChained SubList; - return SubList::print(); - } - - /** Spezialisation for debug-printing of a nested sublist */ - template - struct Printer, BASE> - : BASE - { - static string print () - { - typedef Node List; - return string("\n\t+--") + printSublist()+"+" - + BASE::print(); - } - }; - - template - struct Printer, BASE> - : BASE - { - static string print () - { - typedef typename Config::Flags FlagList; - return string("\n\t+-Conf-[") + printSublist()+"]" - + BASE::print(); - } - }; - - -#define DIAGNOSE(LIST) \ - typedef InstantiateChained Contents_##LIST; - -#define DISPLAY(NAME) \ - DIAGNOSE(NAME); cout << STRINGIFY(NAME) << "\t:" << Contents_##NAME::print() << "\n"; - - - - } // (End) internal defs - - - - } // namespace test - - } // namespace typelist - -} // namespace lumiera -#endif