diff --git a/src/lib/meta/function-erasure.hpp b/src/lib/meta/function-erasure.hpp index 7e18ba090..0696b6a42 100644 --- a/src/lib/meta/function-erasure.hpp +++ b/src/lib/meta/function-erasure.hpp @@ -61,17 +61,25 @@ namespace lumiera { namespace typelist{ - + using std::tr1::function; - /** + /****************************************************** * Generic wrapper carrying a function object * while hiding the actual function signature + * - create it using a function ref or pointer + * - the StoreFunction-policy also allows + * creation based on an existing function object + * - re-access the functor or function ref + * using the templated \c getFun() + * + * @param FH policy to control the implementation. + * In most cases, you should use "StoreFunction" * @note not statically typesafe. Depending on - * the actual embedded container type, - * it \em might be run-time typesafe. + * the specified policy, it \em might be + * run-time typesafe. */ template struct FunErasure @@ -82,7 +90,10 @@ namespace typelist{ : FH(functor) { } }; + + /* ====== Policy classes ====== */ + /** * Policy for FunErasure: store an embedded tr1::function * Using this policy allows to store arbitrary complex functor objects @@ -104,6 +115,7 @@ namespace typelist{ struct FunctionHolder : Holder { typedef function Functor; + FunctionHolder (Functor const& fun) { REQUIRE (SIZE >= sizeof(Functor)); @@ -146,10 +158,10 @@ namespace typelist{ }; - /** + /** * 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. + * while still being able to re-access it later with run-time type check. * The price to pay is vtable access. */ class StoreFunPtr @@ -173,7 +185,7 @@ namespace typelist{ SIG& get() { - return *reinterpret_cast (&fP_); + return *reinterpret_cast (fP_); } }; @@ -202,7 +214,7 @@ namespace typelist{ }; - /** + /** * 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. @@ -227,7 +239,7 @@ namespace typelist{ SIG& getFun () { - return *reinterpret_cast (&funP_); + return *reinterpret_cast (funP_); } }; diff --git a/tests/40components.tests b/tests/40components.tests index e261ba5d0..e28e5445f 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -218,7 +218,7 @@ return: 0 END -PLANNED "FunctionErasure_test" FunctionErasure_test < + 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 @@ -22,17 +22,16 @@ #include "lib/test/run.hpp" +#include "lib/test/test-helper.hpp" #include "lib/meta/function-erasure.hpp" +#include "lib/error.hpp" #include "meta/dummy-functions.hpp" -//#include "lib/util.hpp" -//#include #include -#include using ::test::Test; -using std::string; -using std::cout; +using lumiera::error::LUMIERA_ERROR_ASSERTION; + namespace lumiera { @@ -41,18 +40,19 @@ namespace test { using std::tr1::function; using std::tr1::bind; - + typedef FunErasure Efun; typedef FunErasure Efp; typedef FunErasure Evoid; - /************************************************************************* + + /*********************************************************************** * @test Create specifically typed functor objects and then wrap them * into common holder objects, thereby discarding the specific * signature type information. Later on, the concrete functor * can be re-accessed, given the exact and specific type. - * + * * @see control::FunErasure * @see command-mutation.hpp real world usage example */ @@ -62,29 +62,24 @@ namespace test { run (Arg) { function bindFunc = bind (testFunc,_1,_2); - function pAplFunc = bind (testFunc,_1,'x'); - function memFunc = bind (&FunctionErasure_test::testMemberFunction,this, _1); + function pAplFunc = bind (testFunc,_1,'x'); + function membFunc = bind (&FunctionErasure_test::testMemberFunction,this, _1); function getterFunc = &returnIt; check_FunctorContainer( Efun (testFunc) , Efun (bindFunc) , Efun (pAplFunc) - , Efun (memFunc) + , Efun (membFunc) , Efun (getterFunc) ); - check_FunctPtrHolder(Efp(testFunc) - ,Efp(&testFunc) - , Efp(returnIt)); - - check_VoidPtrHolder(Evoid(testFunc) - ,Evoid(&testFunc) - , Evoid(returnIt)); + check_FunctPtrHolder(Efp(testFunc),Efp(&testFunc), Efp(returnIt)); + check_VoidPtrHolder(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt)); } - + void - testMemberFunction (char c) + testMemberFunction (char c) ///< for checking bind-to member function { return testFunc('a'-'A', c); } @@ -99,7 +94,7 @@ namespace test { typedef int (Sig4) (); _sum_ = 0; - f1.getFun() (-11,'M'); + f1.getFun() (-11,'M'); // invoke stored tr1::function... ASSERT (_sum_ == 'M'-11); _sum_ = 0; @@ -108,35 +103,37 @@ namespace test { _sum_ = 0; f3.getFun() (-33); - ASSERT (_sum_ == 'x'-22); + ASSERT (_sum_ == 'x'-33); _sum_ = 0; f4.getFun() ('U'); ASSERT (_sum_ == 'u'); ASSERT ( 'u' == f5.getFun() () ); + ASSERT (INSTANCEOF (function, &f5.getFun())); + #if false ////////////////////////////////////////////////////////TODO: restore throwing ASSERT VERIFY_ERROR (ASSERTION, f1.getFun() ); VERIFY_ERROR (ASSERTION, f1.getFun() ); VERIFY_ERROR (ASSERTION, f1.getFun() ); - + VERIFY_ERROR (ASSERTION, f2.getFun() ); VERIFY_ERROR (ASSERTION, f3.getFun() ); VERIFY_ERROR (ASSERTION, f2.getFun() ); - + VERIFY_ERROR (ASSERTION, f3.getFun() ); VERIFY_ERROR (ASSERTION, f3.getFun() ); VERIFY_ERROR (ASSERTION, f3.getFun() ); - + VERIFY_ERROR (ASSERTION, f4.getFun() ); VERIFY_ERROR (ASSERTION, f4.getFun() ); VERIFY_ERROR (ASSERTION, f4.getFun() ); - + VERIFY_ERROR (ASSERTION, f5.getFun() ); VERIFY_ERROR (ASSERTION, f5.getFun() ); VERIFY_ERROR (ASSERTION, f5.getFun() ); -#endif +#endif //////////////////////////////////////////////////////// } @@ -151,7 +148,7 @@ namespace test { FR fun2r = f2.getFun(); _sum_ = 0; - (*fun1) (10, 'a'); + (*fun1) (10, 'a'); // invoke retrieved function pointer ASSERT (_sum_ == 10+'a'); (*fun2) (20, 'b'); @@ -164,8 +161,8 @@ namespace test { #if false ////////////////////////////////////////////////////////TODO: restore throwing ASSERT VERIFY_ERROR (ASSERTION, f1.getFun() ); -#endif - +#endif//////////////////////////////////////////////////////////// + } @@ -192,12 +189,10 @@ namespace test { ASSERT (_sum_ == (f3.getFun()) () ); FP bad_fun = &f3.getFun(); - ASSERT ((void*)bad_fun == &returnIt); + ASSERT ((void*)bad_fun == &returnIt); // got wrong function! - (*bad_fun) (11, 'x'); // SEGV - } - - + //(*bad_fun) (11, 'x'); // The compiler would accept this line! + } // likely to result in heap corruption or SEGV };