test pass (resolves Ticket #174)
This commit is contained in:
parent
079030818d
commit
a28c05877f
3 changed files with 53 additions and 46 deletions
|
|
@ -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_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
PLANNED "FunctionErasure_test" FunctionErasure_test <<END
|
||||
TEST "FunctionErasure_test" FunctionErasure_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue