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
|
#ifndef LUMIERA_META_FUNCTION_CLOSURE_H
|
||||||
#define 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/function.hpp"
|
||||||
#include "lib/meta/tuple.hpp"
|
#include "lib/meta/tuple.hpp"
|
||||||
|
|
||||||
#include <tr1/functional>
|
#include <tr1/functional>
|
||||||
|
|
||||||
#include "lib/util.hpp" ////////////////////////TODO
|
|
||||||
#include "lib/error.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace lumiera {
|
namespace lumiera {
|
||||||
namespace typelist{
|
namespace typelist{
|
||||||
|
|
||||||
using std::tr1::bind;
|
|
||||||
//using std::tr1::placeholders::_1;
|
|
||||||
//using std::tr1::placeholders::_2;
|
|
||||||
using std::tr1::function;
|
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;
|
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
|
}} // namespace lumiera::typelist
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,30 @@
|
||||||
|
|
||||||
|
|
||||||
/** @file function-erasure.hpp
|
/** @file function-erasure.hpp
|
||||||
** Partial function application and building a complete function closure.
|
** When working with generic function objects and function pointers typed to
|
||||||
** This is a small addendum to (and thin wrapper for) tr1/functional, supporting
|
** arbitrary signatures, often there is the necessity to hold onto such a functor
|
||||||
** the case when a function should be closed over (all) arguments, where especially
|
** while hiding the actual signature behind an common interface ("type erasure").
|
||||||
** the parameter values to close on are provided as a tuple.
|
** 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
|
** Especially when dealing with tr1::function objects, all of the type differences
|
||||||
** @see function.hpp
|
** are actually encoded into 3 internal pointers, thus yielding the same size for
|
||||||
** @see tuple.hpp
|
** 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
|
#ifndef LUMIERA_META_FUNCTION_ERASURE_H
|
||||||
#define LUMIERA_META_FUNCTION_ERASURE_H
|
#define LUMIERA_META_FUNCTION_ERASURE_H
|
||||||
|
|
||||||
#include "lib/meta/typelist.hpp" /////////////TODO
|
#include "lib/util.hpp"
|
||||||
#include "lib/meta/generator.hpp" /////////////TODO
|
#include "lib/error.hpp"
|
||||||
#include "lib/meta/function.hpp"
|
|
||||||
#include "lib/meta/tuple.hpp"
|
|
||||||
|
|
||||||
#include <tr1/functional>
|
#include <tr1/functional>
|
||||||
|
|
||||||
#include "lib/util.hpp" ////////////////////////TODO
|
|
||||||
#include "lib/error.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace lumiera {
|
namespace lumiera {
|
||||||
namespace typelist{
|
namespace typelist{
|
||||||
|
|
||||||
using std::tr1::bind;
|
|
||||||
//using std::tr1::placeholders::_1;
|
|
||||||
//using std::tr1::placeholders::_2;
|
|
||||||
using std::tr1::function;
|
using std::tr1::function;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -96,19 +104,19 @@ namespace typelist{
|
||||||
struct FunctionHolder : Holder
|
struct FunctionHolder : Holder
|
||||||
{
|
{
|
||||||
typedef function<SIG> Functor;
|
typedef function<SIG> Functor;
|
||||||
FunctionHolder (SIG& fun)
|
FunctionHolder (Functor const& fun)
|
||||||
{
|
{
|
||||||
REQUIRE (SIZE >= sizeof(Functor));
|
REQUIRE (SIZE >= sizeof(Functor));
|
||||||
new(&storage_) Functor (fun);
|
new(&storage_) Functor (fun);
|
||||||
}
|
}
|
||||||
~FunctionHolder()
|
~FunctionHolder()
|
||||||
{
|
{
|
||||||
get()->~Functor();
|
get().~Functor();
|
||||||
}
|
}
|
||||||
Functor&
|
Functor&
|
||||||
get()
|
get()
|
||||||
{
|
{
|
||||||
return static_cast<Functor*> (&storage_);
|
return *reinterpret_cast<Functor*> (&storage_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -119,6 +127,11 @@ namespace typelist{
|
||||||
public:
|
public:
|
||||||
template<typename SIG>
|
template<typename SIG>
|
||||||
StoreFunction (SIG& fun)
|
StoreFunction (SIG& fun)
|
||||||
|
{
|
||||||
|
new(&holder_) FunctionHolder<SIG> (function<SIG>(fun));
|
||||||
|
}
|
||||||
|
template<typename SIG>
|
||||||
|
StoreFunction (function<SIG> const& fun)
|
||||||
{
|
{
|
||||||
new(&holder_) FunctionHolder<SIG> (fun);
|
new(&holder_) FunctionHolder<SIG> (fun);
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +157,7 @@ namespace typelist{
|
||||||
/** Helper: type erasure */
|
/** Helper: type erasure */
|
||||||
struct Holder
|
struct Holder
|
||||||
{
|
{
|
||||||
void *fun_;
|
void *fP_;
|
||||||
virtual ~Holder() {}
|
virtual ~Holder() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -152,14 +165,15 @@ namespace typelist{
|
||||||
template<typename SIG>
|
template<typename SIG>
|
||||||
struct FunctionHolder : Holder
|
struct FunctionHolder : Holder
|
||||||
{
|
{
|
||||||
FunctionHolder (SIG& fun)
|
FunctionHolder (SIG *fun)
|
||||||
{
|
{
|
||||||
fun_ = &fun;
|
REQUIRE (fun);
|
||||||
|
fP_ = reinterpret_cast<void*> (fun);
|
||||||
}
|
}
|
||||||
SIG&
|
SIG&
|
||||||
get()
|
get()
|
||||||
{
|
{
|
||||||
return reinterpret_cast<SIG*> (&fun_);
|
return *reinterpret_cast<SIG*> (&fP_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -169,12 +183,17 @@ namespace typelist{
|
||||||
public:
|
public:
|
||||||
template<typename SIG>
|
template<typename SIG>
|
||||||
StoreFunPtr (SIG& fun)
|
StoreFunPtr (SIG& fun)
|
||||||
|
{
|
||||||
|
new(&holder_) FunctionHolder<SIG> (&fun);
|
||||||
|
}
|
||||||
|
template<typename SIG>
|
||||||
|
StoreFunPtr (SIG *fun)
|
||||||
{
|
{
|
||||||
new(&holder_) FunctionHolder<SIG> (fun);
|
new(&holder_) FunctionHolder<SIG> (fun);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename SIG>
|
template<typename SIG>
|
||||||
function<SIG>&
|
SIG&
|
||||||
getFun ()
|
getFun ()
|
||||||
{
|
{
|
||||||
REQUIRE (INSTANCEOF (FunctionHolder<SIG>, &holder_));
|
REQUIRE (INSTANCEOF (FunctionHolder<SIG>, &holder_));
|
||||||
|
|
@ -190,20 +209,25 @@ namespace typelist{
|
||||||
*/
|
*/
|
||||||
class StoreUncheckedFunPtr
|
class StoreUncheckedFunPtr
|
||||||
{
|
{
|
||||||
void *fun_;
|
void *funP_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename SIG>
|
template<typename SIG>
|
||||||
StoreUncheckedFunPtr (SIG& fun)
|
StoreUncheckedFunPtr (SIG& fun)
|
||||||
{
|
{
|
||||||
fun_ = &fun;
|
funP_ = reinterpret_cast<void*> (&fun);
|
||||||
|
}
|
||||||
|
template<typename SIG>
|
||||||
|
StoreUncheckedFunPtr (SIG *fun)
|
||||||
|
{
|
||||||
|
funP_ = reinterpret_cast<void*> (fun);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename SIG>
|
template<typename SIG>
|
||||||
SIG&
|
SIG&
|
||||||
getFun ()
|
getFun ()
|
||||||
{
|
{
|
||||||
return reinterpret_cast<SIG*> (&fun_);
|
return *reinterpret_cast<SIG*> (&funP_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,16 @@ out: dtor ~TargetObj\(12\) successful
|
||||||
END
|
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
|
TEST "HashIndexed_test" HashIndexed_test <<END
|
||||||
return: 0
|
return: 0
|
||||||
END
|
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
|
/** @file function-closure-test.cpp
|
||||||
** bla
|
**
|
||||||
|
** @todo define function-closure-test
|
||||||
**
|
**
|
||||||
** @see function-closure.hpp
|
** @see function-closure.hpp
|
||||||
** @see control::CmdClosure real world usage example
|
** @see control::CmdClosure real world usage example
|
||||||
|
|
@ -32,7 +33,8 @@
|
||||||
|
|
||||||
#include "lib/test/run.hpp"
|
#include "lib/test/run.hpp"
|
||||||
#include "lib/meta/function-closure.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 <boost/format.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -47,13 +49,6 @@ namespace typelist{
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
|
||||||
namespace { // test data
|
|
||||||
|
|
||||||
} // (End) test data
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
@ -62,23 +57,11 @@ namespace test {
|
||||||
*/
|
*/
|
||||||
class FunctionClosure_test : public Test
|
class FunctionClosure_test : public Test
|
||||||
{
|
{
|
||||||
virtual void run(Arg arg)
|
virtual void
|
||||||
|
run (Arg)
|
||||||
{
|
{
|
||||||
check_distribute();
|
UNIMPLEMENTED ("verify function closure utils");
|
||||||
check_combine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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/test/run.hpp"
|
||||||
#include "lib/meta/function-erasure.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 <boost/format.hpp>
|
||||||
|
#include <tr1/functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using ::test::Test;
|
using ::test::Test;
|
||||||
|
|
@ -46,36 +39,162 @@ namespace lumiera {
|
||||||
namespace typelist{
|
namespace typelist{
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
using std::tr1::function;
|
||||||
namespace { // test data
|
using std::tr1::bind;
|
||||||
|
|
||||||
} // (End) test data
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef FunErasure<StoreFunction> Efun;
|
||||||
|
typedef FunErasure<StoreFunPtr> Efp;
|
||||||
|
typedef FunErasure<StoreUncheckedFunPtr> Evoid;
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* @test //////////////////////////////////////////
|
* @test Create specifically typed functor objects and then wrap them
|
||||||
* - building combinations and permutations
|
* 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
|
class FunctionErasure_test : public Test
|
||||||
{
|
{
|
||||||
virtual void run(Arg arg)
|
virtual void
|
||||||
|
run (Arg)
|
||||||
{
|
{
|
||||||
check_distribute();
|
function<void(int,char)> bindFunc = bind (testFunc,_1,_2);
|
||||||
check_combine();
|
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_distribute()
|
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_combine()
|
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