use the new bool conversion mixin to implement check for valid functor
This commit is contained in:
parent
b45cd49c8b
commit
8ea07bda7a
3 changed files with 33 additions and 37 deletions
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
#include "lib/util.hpp"
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/bool-checkable.hpp"
|
||||
|
||||
#include <tr1/functional>
|
||||
|
||||
|
|
@ -76,7 +77,7 @@ namespace typelist{
|
|||
* using the templated \c getFun()
|
||||
*
|
||||
* @param FH policy to control the implementation.
|
||||
* In most cases, you should use "StoreFunction"
|
||||
* In most cases, you should use "StoreFunction"
|
||||
* @note not statically typesafe. Depending on
|
||||
* the specified policy, it \em might be
|
||||
* run-time typesafe.
|
||||
|
|
@ -91,40 +92,19 @@ namespace typelist{
|
|||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ====== Policy classes ====== */
|
||||
|
||||
template<class T>
|
||||
struct BoolCheckable
|
||||
{
|
||||
typedef bool (T::*ValidityCheck)() const;
|
||||
typedef ValidityCheck _unspecified_bool_type;
|
||||
|
||||
/** implicit conversion to "bool" */
|
||||
operator _unspecified_bool_type() const ///< never throws
|
||||
{
|
||||
ValidityCheck isValid (&T::isValid);
|
||||
T const& obj = static_cast<T const&> (*this);
|
||||
return (obj.*isValid)()? isValid : 0;
|
||||
}
|
||||
|
||||
bool operator! () const ///< never throws
|
||||
{
|
||||
ValidityCheck isValid (&T::isValid);
|
||||
T const& obj = static_cast<T const&> (*this);
|
||||
return !(obj.*isValid)();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* The price to pay is vtable access and heap storage of function arguments.
|
||||
*
|
||||
* @note the bool conversion and #isValid are highly implementation dependent
|
||||
*/
|
||||
class StoreFunction
|
||||
// : public BoolCheckable<StoreFunction>
|
||||
: public lib::BoolCheckable<StoreFunction>
|
||||
{
|
||||
/** Helper: type erasure */
|
||||
struct Holder
|
||||
|
|
@ -181,7 +161,7 @@ namespace typelist{
|
|||
}
|
||||
|
||||
bool
|
||||
isValid() const
|
||||
isValid() const ///< @note implementation dependent!!
|
||||
{
|
||||
return reinterpret_cast<void*> (holder_.storage_[0]);
|
||||
}
|
||||
|
|
@ -195,6 +175,7 @@ namespace typelist{
|
|||
* The price to pay is vtable access.
|
||||
*/
|
||||
class StoreFunPtr
|
||||
: public lib::BoolCheckable<StoreFunPtr>
|
||||
{
|
||||
/** Helper: type erasure */
|
||||
struct Holder
|
||||
|
|
@ -241,6 +222,13 @@ namespace typelist{
|
|||
REQUIRE (INSTANCEOF (FunctionHolder<SIG>, &holder_));
|
||||
return static_cast<FunctionHolder<SIG>&> (holder_).get();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
isValid() const
|
||||
{
|
||||
return holder_.fP_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -250,6 +238,7 @@ namespace typelist{
|
|||
* and to retrieve it without overhead, but also without safety.
|
||||
*/
|
||||
class StoreUncheckedFunPtr
|
||||
: public lib::BoolCheckable<StoreUncheckedFunPtr>
|
||||
{
|
||||
void *funP_;
|
||||
|
||||
|
|
@ -271,6 +260,13 @@ namespace typelist{
|
|||
{
|
||||
return *reinterpret_cast<SIG*> (funP_);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
isValid() const
|
||||
{
|
||||
return funP_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ namespace control {
|
|||
close (CmdClosure& cmdClosure)
|
||||
{
|
||||
REQUIRE (!clo_, "Lifecycle error: already closed over the arguments");
|
||||
// REQUIRE (func_, "Param error: not bound to a valid function");
|
||||
REQUIRE (func_, "Param error: not bound to a valid function");
|
||||
func_ = cmdClosure.bindArguments(func_);
|
||||
clo_ = &cmdClosure;
|
||||
return *this;
|
||||
|
|
@ -117,7 +117,7 @@ namespace control {
|
|||
virtual bool
|
||||
isValid () const
|
||||
{
|
||||
// return func_ && clo_;
|
||||
return func_ && clo_;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -177,7 +177,7 @@ namespace control {
|
|||
close (CmdClosure& cmdClosure)
|
||||
{
|
||||
REQUIRE (!memento_, "Lifecycle error: already closed over the arguments");
|
||||
// REQUIRE (captureFunc_, "Param error: not bound to a valid function");
|
||||
REQUIRE (captureFunc_, "Param error: not bound to a valid function");
|
||||
|
||||
// create a special state closure, which can later on store the captured undo state (memento)
|
||||
scoped_ptr<CmdClosure> stateClosure (new MementoClosure (captureFunc_));
|
||||
|
|
@ -213,7 +213,7 @@ namespace control {
|
|||
virtual bool
|
||||
isValid () const
|
||||
{
|
||||
// return Mutation::isValid() && captureFunc_ && memento_;
|
||||
return Mutation::isValid() && captureFunc_ && memento_;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -212,10 +212,10 @@ namespace test {
|
|||
|
||||
typedef typename BuildEmptyHolder<HOL>::Type EmptyHolder;
|
||||
EmptyHolder emptyHolder;
|
||||
// ASSERT (!emptyHolder);
|
||||
// ASSERT ( h1 );
|
||||
// ASSERT ( h2 );
|
||||
// ASSERT ( h3 );
|
||||
ASSERT (!emptyHolder);
|
||||
ASSERT ( h1 );
|
||||
ASSERT ( h2 );
|
||||
ASSERT ( h3 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue