draft a test to sharpen the idea of the function holder (erasure)
This commit is contained in:
parent
a565bfef73
commit
079030818d
6 changed files with 283 additions and 245 deletions
|
|
@ -37,28 +37,22 @@
|
|||
#ifndef LUMIERA_META_FUNCTION_CLOSURE_H
|
||||
#define LUMIERA_META_FUNCTION_CLOSURE_H
|
||||
|
||||
#include "lib/meta/typelist.hpp" /////////////TODO
|
||||
#include "lib/meta/generator.hpp" /////////////TODO
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/meta/tuple.hpp"
|
||||
|
||||
#include <tr1/functional>
|
||||
|
||||
#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;
|
||||
using std::tr1::bind;
|
||||
|
||||
|
||||
|
||||
namespace func { // helpers for binding and applying a function to an argument tuple
|
||||
namespace func { ///< helpers for binding and applying a function to an argument tuple
|
||||
|
||||
using tuple::element;
|
||||
|
||||
|
|
@ -392,157 +386,5 @@ namespace typelist{
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* 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<class FH>
|
||||
struct FunErasure
|
||||
: FH
|
||||
{
|
||||
template<typename FUN>
|
||||
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<void(void)>) };
|
||||
char storage_[SIZE];
|
||||
virtual ~Holder() {}
|
||||
};
|
||||
|
||||
/** embedding the concrete functor object */
|
||||
template<typename SIG>
|
||||
struct FunctionHolder : Holder
|
||||
{
|
||||
typedef function<SIG> Functor;
|
||||
FunctionHolder (SIG& fun)
|
||||
{
|
||||
REQUIRE (SIZE >= sizeof(Functor));
|
||||
new(&storage_) Functor (fun);
|
||||
}
|
||||
~FunctionHolder()
|
||||
{
|
||||
get()->~Functor();
|
||||
}
|
||||
Functor&
|
||||
get()
|
||||
{
|
||||
return static_cast<Functor*> (&storage_);
|
||||
}
|
||||
};
|
||||
|
||||
/** embedded buffer actually holding
|
||||
* the concrete Functor object */
|
||||
Holder holder_;
|
||||
|
||||
public:
|
||||
template<typename SIG>
|
||||
StoreFunction (SIG& fun)
|
||||
{
|
||||
new(&holder_) FunctionHolder<SIG> (fun);
|
||||
}
|
||||
|
||||
template<typename SIG>
|
||||
function<SIG>&
|
||||
getFun ()
|
||||
{
|
||||
REQUIRE (INSTANCEOF (FunctionHolder<SIG>, &holder_));
|
||||
return static_cast<FunctionHolder<SIG>&> (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<typename SIG>
|
||||
struct FunctionHolder : Holder
|
||||
{
|
||||
FunctionHolder (SIG& fun)
|
||||
{
|
||||
fun_ = &fun;
|
||||
}
|
||||
SIG&
|
||||
get()
|
||||
{
|
||||
return reinterpret_cast<SIG*> (&fun_);
|
||||
}
|
||||
};
|
||||
|
||||
/** embedded container holding the pointer */
|
||||
Holder holder_;
|
||||
|
||||
public:
|
||||
template<typename SIG>
|
||||
StoreFunPtr (SIG& fun)
|
||||
{
|
||||
new(&holder_) FunctionHolder<SIG> (fun);
|
||||
}
|
||||
|
||||
template<typename SIG>
|
||||
function<SIG>&
|
||||
getFun ()
|
||||
{
|
||||
REQUIRE (INSTANCEOF (FunctionHolder<SIG>, &holder_));
|
||||
return static_cast<FunctionHolder<SIG>&> (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<typename SIG>
|
||||
StoreUncheckedFunPtr (SIG& fun)
|
||||
{
|
||||
fun_ = &fun;
|
||||
}
|
||||
|
||||
template<typename SIG>
|
||||
SIG&
|
||||
getFun ()
|
||||
{
|
||||
return reinterpret_cast<SIG*> (&fun_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}} // namespace lumiera::typelist
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,14 +22,30 @@
|
|||
|
||||
|
||||
/** @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.
|
||||
** When working with generic function objects and function pointers typed to
|
||||
** arbitrary signatures, often there is the necessity to hold onto such a functor
|
||||
** while hiding the actual signature behind an common interface ("type erasure").
|
||||
** The usual solution based on subclassing has the downside of requiring separate
|
||||
** storage for the concrete functor object, which might become problematic when
|
||||
** dealing with lots of functor objects.
|
||||
**
|
||||
** @see control::CommandDef usage example
|
||||
** @see function.hpp
|
||||
** @see tuple.hpp
|
||||
** Especially when dealing with tr1::function objects, all of the type differences
|
||||
** are actually encoded into 3 internal pointers, thus yielding the same size for
|
||||
** all various types of functors. Building on this observation, we can create an
|
||||
** common container object to store the varying functors inline, while hiding the
|
||||
** actual signature.
|
||||
**
|
||||
** There remains the problem of re-accessing the concrete functor later on. As
|
||||
** C++ has only rudimental introspection capabilities, we can only rely on the
|
||||
** usage context to provide the correct function signature; only when using a
|
||||
** virtual function for the re-access, we can perform at least a runtime-check.
|
||||
**
|
||||
** Thus there are various flavours for actually implementing this idea, and the
|
||||
** picking a suitable implementation depends largely on the context. Thus we
|
||||
** provide a common and expect the client code to pick an implementation policy.
|
||||
**
|
||||
** @see control::Mutation usage example
|
||||
** @see function-erasure-test.cpp
|
||||
**
|
||||
*/
|
||||
|
||||
|
|
@ -37,23 +53,15 @@
|
|||
#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 "lib/util.hpp"
|
||||
#include "lib/error.hpp"
|
||||
|
||||
#include <tr1/functional>
|
||||
|
||||
#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;
|
||||
|
||||
|
||||
|
|
@ -96,19 +104,19 @@ namespace typelist{
|
|||
struct FunctionHolder : Holder
|
||||
{
|
||||
typedef function<SIG> Functor;
|
||||
FunctionHolder (SIG& fun)
|
||||
FunctionHolder (Functor const& fun)
|
||||
{
|
||||
REQUIRE (SIZE >= sizeof(Functor));
|
||||
new(&storage_) Functor (fun);
|
||||
}
|
||||
~FunctionHolder()
|
||||
{
|
||||
get()->~Functor();
|
||||
get().~Functor();
|
||||
}
|
||||
Functor&
|
||||
get()
|
||||
{
|
||||
return static_cast<Functor*> (&storage_);
|
||||
return *reinterpret_cast<Functor*> (&storage_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -119,6 +127,11 @@ namespace typelist{
|
|||
public:
|
||||
template<typename SIG>
|
||||
StoreFunction (SIG& fun)
|
||||
{
|
||||
new(&holder_) FunctionHolder<SIG> (function<SIG>(fun));
|
||||
}
|
||||
template<typename SIG>
|
||||
StoreFunction (function<SIG> const& fun)
|
||||
{
|
||||
new(&holder_) FunctionHolder<SIG> (fun);
|
||||
}
|
||||
|
|
@ -144,7 +157,7 @@ namespace typelist{
|
|||
/** Helper: type erasure */
|
||||
struct Holder
|
||||
{
|
||||
void *fun_;
|
||||
void *fP_;
|
||||
virtual ~Holder() {}
|
||||
};
|
||||
|
||||
|
|
@ -152,14 +165,15 @@ namespace typelist{
|
|||
template<typename SIG>
|
||||
struct FunctionHolder : Holder
|
||||
{
|
||||
FunctionHolder (SIG& fun)
|
||||
FunctionHolder (SIG *fun)
|
||||
{
|
||||
fun_ = &fun;
|
||||
REQUIRE (fun);
|
||||
fP_ = reinterpret_cast<void*> (fun);
|
||||
}
|
||||
SIG&
|
||||
get()
|
||||
{
|
||||
return reinterpret_cast<SIG*> (&fun_);
|
||||
return *reinterpret_cast<SIG*> (&fP_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -169,12 +183,17 @@ namespace typelist{
|
|||
public:
|
||||
template<typename SIG>
|
||||
StoreFunPtr (SIG& fun)
|
||||
{
|
||||
new(&holder_) FunctionHolder<SIG> (&fun);
|
||||
}
|
||||
template<typename SIG>
|
||||
StoreFunPtr (SIG *fun)
|
||||
{
|
||||
new(&holder_) FunctionHolder<SIG> (fun);
|
||||
}
|
||||
|
||||
template<typename SIG>
|
||||
function<SIG>&
|
||||
SIG&
|
||||
getFun ()
|
||||
{
|
||||
REQUIRE (INSTANCEOF (FunctionHolder<SIG>, &holder_));
|
||||
|
|
@ -190,20 +209,25 @@ namespace typelist{
|
|||
*/
|
||||
class StoreUncheckedFunPtr
|
||||
{
|
||||
void *fun_;
|
||||
void *funP_;
|
||||
|
||||
public:
|
||||
template<typename SIG>
|
||||
StoreUncheckedFunPtr (SIG& fun)
|
||||
{
|
||||
fun_ = &fun;
|
||||
funP_ = reinterpret_cast<void*> (&fun);
|
||||
}
|
||||
template<typename SIG>
|
||||
StoreUncheckedFunPtr (SIG *fun)
|
||||
{
|
||||
funP_ = reinterpret_cast<void*> (fun);
|
||||
}
|
||||
|
||||
template<typename SIG>
|
||||
SIG&
|
||||
getFun ()
|
||||
{
|
||||
return reinterpret_cast<SIG*> (&fun_);
|
||||
return *reinterpret_cast<SIG*> (&funP_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -213,6 +213,16 @@ out: dtor ~TargetObj\(12\) successful
|
|||
END
|
||||
|
||||
|
||||
PLANNED "FunctionClosure_test" FunctionClosure_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
PLANNED "FunctionErasure_test" FunctionErasure_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "HashIndexed_test" HashIndexed_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
|
|
|||
60
tests/lib/meta/dummy-functions.hpp
Normal file
60
tests/lib/meta/dummy-functions.hpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
DUMMY-FUNCTIONS - mock functions for checking functor utils
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
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
|
||||
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.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
#ifndef LIB_META_DUMMY_FUNCTIONS_H
|
||||
#define LIB_META_DUMMY_FUNCTIONS_H
|
||||
|
||||
|
||||
//#include <boost/format.hpp>
|
||||
//#include <string>
|
||||
|
||||
//using std::string;
|
||||
//using boost::format;
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
namespace typelist{
|
||||
namespace test {
|
||||
|
||||
|
||||
namespace { // test helpers
|
||||
|
||||
int _sum_ =0; ///< used to verify the effect of testFunc
|
||||
|
||||
void
|
||||
testFunc (int i, char c)
|
||||
{
|
||||
_sum_ += i + c;
|
||||
}
|
||||
|
||||
int
|
||||
returnIt ()
|
||||
{
|
||||
return _sum_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}}} // namespace lumiera::typelist::test
|
||||
#endif
|
||||
|
|
@ -22,7 +22,8 @@
|
|||
|
||||
|
||||
/** @file function-closure-test.cpp
|
||||
** bla
|
||||
**
|
||||
** @todo define function-closure-test
|
||||
**
|
||||
** @see function-closure.hpp
|
||||
** @see control::CmdClosure real world usage example
|
||||
|
|
@ -32,7 +33,8 @@
|
|||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/meta/function-closure.hpp"
|
||||
#include "lib/util.hpp"
|
||||
#include "meta/dummy-functions.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
//#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
|
@ -47,13 +49,6 @@ namespace typelist{
|
|||
namespace test {
|
||||
|
||||
|
||||
namespace { // test data
|
||||
|
||||
} // (End) test data
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
|
|
@ -62,23 +57,11 @@ namespace test {
|
|||
*/
|
||||
class FunctionClosure_test : public Test
|
||||
{
|
||||
virtual void run(Arg arg)
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
check_distribute();
|
||||
check_combine();
|
||||
UNIMPLEMENTED ("verify function closure utils");
|
||||
}
|
||||
|
||||
|
||||
void check_distribute()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void check_combine()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,20 +21,13 @@
|
|||
* *****************************************************/
|
||||
|
||||
|
||||
/** @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 "meta/dummy-functions.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
//#include <boost/format.hpp>
|
||||
#include <tr1/functional>
|
||||
#include <iostream>
|
||||
|
||||
using ::test::Test;
|
||||
|
|
@ -46,38 +39,164 @@ namespace lumiera {
|
|||
namespace typelist{
|
||||
namespace test {
|
||||
|
||||
using std::tr1::function;
|
||||
using std::tr1::bind;
|
||||
|
||||
|
||||
namespace { // test data
|
||||
|
||||
} // (End) test data
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef FunErasure<StoreFunction> Efun;
|
||||
typedef FunErasure<StoreFunPtr> Efp;
|
||||
typedef FunErasure<StoreUncheckedFunPtr> Evoid;
|
||||
|
||||
/*************************************************************************
|
||||
* @test //////////////////////////////////////////
|
||||
* - building combinations and permutations
|
||||
* @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
|
||||
*/
|
||||
class FunctionErasure_test : public Test
|
||||
{
|
||||
virtual void run(Arg arg)
|
||||
{
|
||||
check_distribute();
|
||||
check_combine();
|
||||
}
|
||||
|
||||
|
||||
void check_distribute()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void check_combine()
|
||||
virtual void
|
||||
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<int(void)> getterFunc = &returnIt;
|
||||
|
||||
check_FunctorContainer( Efun (testFunc)
|
||||
, Efun (bindFunc)
|
||||
, Efun (pAplFunc)
|
||||
, Efun (memFunc)
|
||||
, Efun (getterFunc)
|
||||
);
|
||||
|
||||
check_FunctPtrHolder(Efp(testFunc)
|
||||
,Efp(&testFunc)
|
||||
, Efp(returnIt));
|
||||
|
||||
check_VoidPtrHolder(Evoid(testFunc)
|
||||
,Evoid(&testFunc)
|
||||
, Evoid(returnIt));
|
||||
}
|
||||
|
||||
void
|
||||
testMemberFunction (char c)
|
||||
{
|
||||
return testFunc('a'-'A', c);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
check_FunctorContainer (Efun f1, Efun f2, Efun f3, Efun f4, Efun f5)
|
||||
{
|
||||
typedef void (Sig1) (int,char);
|
||||
typedef void (Sig2) (int);
|
||||
typedef void (Sig3) (char);
|
||||
typedef int (Sig4) ();
|
||||
|
||||
_sum_ = 0;
|
||||
f1.getFun<Sig1>() (-11,'M');
|
||||
ASSERT (_sum_ == 'M'-11);
|
||||
|
||||
_sum_ = 0;
|
||||
f2.getFun<Sig1>() (-22,'M');
|
||||
ASSERT (_sum_ == 'M'-22);
|
||||
|
||||
_sum_ = 0;
|
||||
f3.getFun<Sig2>() (-33);
|
||||
ASSERT (_sum_ == 'x'-22);
|
||||
|
||||
_sum_ = 0;
|
||||
f4.getFun<Sig3>() ('U');
|
||||
ASSERT (_sum_ == 'u');
|
||||
|
||||
ASSERT ( 'u' == 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
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
check_FunctPtrHolder (Efp f1, Efp f2, Efp f3)
|
||||
{
|
||||
typedef void (*FP)(int,char);
|
||||
typedef void (&FR)(int,char);
|
||||
|
||||
FP fun1 = &f1.getFun<void(int,char)>();
|
||||
FP fun2 = &f2.getFun<void(int,char)>();
|
||||
FR fun2r = f2.getFun<void(int,char)>();
|
||||
|
||||
_sum_ = 0;
|
||||
(*fun1) (10, 'a');
|
||||
ASSERT (_sum_ == 10+'a');
|
||||
|
||||
(*fun2) (20, 'b');
|
||||
ASSERT (_sum_ == 10+'a'+20+'b');
|
||||
|
||||
fun2r (30, 'c');
|
||||
ASSERT (_sum_ == 10+'a'+20+'b'+30+'c');
|
||||
|
||||
ASSERT (_sum_ == (f3.getFun<int(void)>()) () );
|
||||
|
||||
#if false ////////////////////////////////////////////////////////TODO: restore throwing ASSERT
|
||||
VERIFY_ERROR (ASSERTION, f1.getFun<int(int)>() );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
check_VoidPtrHolder (Evoid f1, Evoid f2, Evoid f3)
|
||||
{
|
||||
typedef void (*FP)(int,char);
|
||||
typedef void (&FR)(int,char);
|
||||
|
||||
FP fun1 = &f1.getFun<void(int,char)>();
|
||||
FP fun2 = &f2.getFun<void(int,char)>();
|
||||
FR fun2r = f2.getFun<void(int,char)>();
|
||||
|
||||
_sum_ = 0;
|
||||
(*fun1) (10, 'a');
|
||||
ASSERT (_sum_ == 10+'a');
|
||||
|
||||
(*fun2) (20, 'b');
|
||||
ASSERT (_sum_ == 10+'a'+20+'b');
|
||||
|
||||
fun2r (30, 'c');
|
||||
ASSERT (_sum_ == 10+'a'+20+'b'+30+'c');
|
||||
|
||||
ASSERT (_sum_ == (f3.getFun<int(void)>()) () );
|
||||
|
||||
FP bad_fun = &f3.getFun<void(int,char)>();
|
||||
ASSERT ((void*)bad_fun == &returnIt);
|
||||
|
||||
(*bad_fun) (11, 'x'); // SEGV
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue