test pass (resolves Ticket #174)

This commit is contained in:
Fischlurch 2009-06-20 06:11:09 +02:00
parent 079030818d
commit a28c05877f
3 changed files with 53 additions and 46 deletions

View file

@ -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<class FH>
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<SIG> 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<SIG*> (&fP_);
return *reinterpret_cast<SIG*> (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<SIG*> (&funP_);
return *reinterpret_cast<SIG*> (funP_);
}
};

View file

@ -218,7 +218,7 @@ return: 0
END
PLANNED "FunctionErasure_test" FunctionErasure_test <<END
TEST "FunctionErasure_test" FunctionErasure_test <<END
return: 0
END

View file

@ -2,7 +2,7 @@
FunctionErasure(Test) - verify the wrapping of functor object with type erasure
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
2009, Hermann Vosseler <Ichthyostega@web.de>
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 <boost/format.hpp>
#include <tr1/functional>
#include <iostream>
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<StoreFunction> Efun;
typedef FunErasure<StoreFunPtr> Efp;
typedef FunErasure<StoreUncheckedFunPtr> 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<void(int,char)> bindFunc = bind (testFunc,_1,_2);
function<void(int,char)> pAplFunc = bind (testFunc,_1,'x');
function<void(int,char)> memFunc = bind (&FunctionErasure_test::testMemberFunction,this, _1);
function<void(int )> pAplFunc = bind (testFunc,_1,'x');
function<void( char)> membFunc = bind (&FunctionErasure_test::testMemberFunction,this, _1);
function<int(void)> 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<Sig1>() (-11,'M');
f1.getFun<Sig1>() (-11,'M'); // invoke stored tr1::function...
ASSERT (_sum_ == 'M'-11);
_sum_ = 0;
@ -108,35 +103,37 @@ namespace test {
_sum_ = 0;
f3.getFun<Sig2>() (-33);
ASSERT (_sum_ == 'x'-22);
ASSERT (_sum_ == 'x'-33);
_sum_ = 0;
f4.getFun<Sig3>() ('U');
ASSERT (_sum_ == 'u');
ASSERT ( 'u' == f5.getFun<Sig4>() () );
ASSERT (INSTANCEOF (function<Sig4>, &f5.getFun<Sig4>()));
#if false ////////////////////////////////////////////////////////TODO: restore throwing ASSERT
VERIFY_ERROR (ASSERTION, f1.getFun<Sig2>() );
VERIFY_ERROR (ASSERTION, f1.getFun<Sig3>() );
VERIFY_ERROR (ASSERTION, f1.getFun<Sig4>() );
VERIFY_ERROR (ASSERTION, f2.getFun<Sig2>() );
VERIFY_ERROR (ASSERTION, f3.getFun<Sig3>() );
VERIFY_ERROR (ASSERTION, f2.getFun<Sig4>() );
VERIFY_ERROR (ASSERTION, f3.getFun<Sig1>() );
VERIFY_ERROR (ASSERTION, f3.getFun<Sig3>() );
VERIFY_ERROR (ASSERTION, f3.getFun<Sig4>() );
VERIFY_ERROR (ASSERTION, f4.getFun<Sig1>() );
VERIFY_ERROR (ASSERTION, f4.getFun<Sig2>() );
VERIFY_ERROR (ASSERTION, f4.getFun<Sig4>() );
VERIFY_ERROR (ASSERTION, f5.getFun<Sig1>() );
VERIFY_ERROR (ASSERTION, f5.getFun<Sig2>() );
VERIFY_ERROR (ASSERTION, f5.getFun<Sig3>() );
#endif
#endif ////////////////////////////////////////////////////////
}
@ -151,7 +148,7 @@ namespace test {
FR fun2r = f2.getFun<void(int,char)>();
_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<int(int)>() );
#endif
#endif////////////////////////////////////////////////////////////
}
@ -192,12 +189,10 @@ namespace test {
ASSERT (_sum_ == (f3.getFun<int(void)>()) () );
FP bad_fun = &f3.getFun<void(int,char)>();
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
};