add operator== to Functor, initiated by Eric Beyeler
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@662 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
c272535c72
commit
50d35c6196
2 changed files with 244 additions and 12 deletions
|
@ -34,6 +34,12 @@
|
||||||
//#define LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
|
//#define LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
//#define LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#define LOKI_FUNCTOR_DEBUG
|
||||||
|
|
||||||
/// \namespace Loki
|
/// \namespace Loki
|
||||||
/// All classes of Loki are in the Loki namespace
|
/// All classes of Loki are in the Loki namespace
|
||||||
namespace Loki
|
namespace Loki
|
||||||
|
@ -58,6 +64,7 @@ namespace Loki
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef R ResultType;
|
typedef R ResultType;
|
||||||
|
typedef FunctorImplBase<R, ThreadingModel> FunctorImplBaseType;
|
||||||
|
|
||||||
typedef EmptyType Parm1;
|
typedef EmptyType Parm1;
|
||||||
typedef EmptyType Parm2;
|
typedef EmptyType Parm2;
|
||||||
|
@ -85,10 +92,25 @@ namespace Loki
|
||||||
static U* Clone(U* pObj)
|
static U* Clone(U* pObj)
|
||||||
{
|
{
|
||||||
if (!pObj) return 0;
|
if (!pObj) return 0;
|
||||||
|
#ifdef LOKI_FUNCTOR_DEBUG
|
||||||
|
U* pClone = dynamic_cast<U*>(pObj->DoClone());
|
||||||
|
#else
|
||||||
U* pClone = static_cast<U*>(pObj->DoClone());
|
U* pClone = static_cast<U*>(pObj->DoClone());
|
||||||
|
#endif
|
||||||
assert(typeid(*pClone) == typeid(*pObj));
|
assert(typeid(*pClone) == typeid(*pObj));
|
||||||
return pClone;
|
return pClone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
|
||||||
|
virtual bool operator==(const FunctorImplBase&) const = 0;
|
||||||
|
|
||||||
|
// there is no static information if Functor holds a member function
|
||||||
|
// or a free function; this is the main difference to tr1::function
|
||||||
|
virtual bool isMemberFuncPtr() const = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,6 +958,28 @@ namespace Loki
|
||||||
|
|
||||||
LOKI_DEFINE_CLONE_FUNCTORIMPL(FunctorHandler)
|
LOKI_DEFINE_CLONE_FUNCTORIMPL(FunctorHandler)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
|
||||||
|
bool isMemberFuncPtr() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const typename Base::FunctorImplBaseType& rhs) const
|
||||||
|
{
|
||||||
|
if( rhs.isMemberFuncPtr() )
|
||||||
|
return false; // cannot be equal
|
||||||
|
#ifdef LOKI_FUNCTOR_DEBUG
|
||||||
|
const FunctorHandler& fh = dynamic_cast<const FunctorHandler&>(rhs);
|
||||||
|
#else
|
||||||
|
const FunctorHandler& fh = static_cast<const FunctorHandler&>(rhs);
|
||||||
|
#endif
|
||||||
|
// if this line gives a compiler error, you are using a function object.
|
||||||
|
// you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
|
||||||
|
return f_==fh.f_;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// operator() implementations for up to 15 arguments
|
// operator() implementations for up to 15 arguments
|
||||||
|
|
||||||
ResultType operator()()
|
ResultType operator()()
|
||||||
|
@ -1045,6 +1089,30 @@ namespace Loki
|
||||||
|
|
||||||
LOKI_DEFINE_CLONE_FUNCTORIMPL(MemFunHandler)
|
LOKI_DEFINE_CLONE_FUNCTORIMPL(MemFunHandler)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
|
||||||
|
bool isMemberFuncPtr() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const typename Base::FunctorImplBaseType& rhs) const
|
||||||
|
{
|
||||||
|
if(!rhs.isMemberFuncPtr())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef LOKI_FUNCTOR_DEBUG
|
||||||
|
const MemFunHandler& mfh = dynamic_cast<const MemFunHandler&>(rhs);
|
||||||
|
#else
|
||||||
|
const MemFunHandler& mfh = static_cast<const MemFunHandler&>(rhs);
|
||||||
|
#endif
|
||||||
|
// if this line gives a compiler error, you are using a function object.
|
||||||
|
// you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
|
||||||
|
return pObj_==mfh.pObj_ && pMemFn_==mfh.pMemFn_;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ResultType operator()()
|
ResultType operator()()
|
||||||
{ return ((*pObj_).*pMemFn_)(); }
|
{ return ((*pObj_).*pMemFn_)(); }
|
||||||
|
|
||||||
|
@ -1162,6 +1230,13 @@ namespace Loki
|
||||||
/// It often helps against crashes when using static Functors and multi threading.
|
/// It often helps against crashes when using static Functors and multi threading.
|
||||||
/// Defining also removes problems when unloading Dlls which hosts
|
/// Defining also removes problems when unloading Dlls which hosts
|
||||||
/// static Functor objects.
|
/// static Functor objects.
|
||||||
|
///
|
||||||
|
/// \par Macro: LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
/// To enable the operator== define the macro
|
||||||
|
/// \code LOKI_FUNCTORS_ARE_COMPARABLE \endcode
|
||||||
|
/// The macro is disabled by default, because it breaks compiling functor
|
||||||
|
/// objects which have no operator== implemented, keep in mind when you enable
|
||||||
|
/// operator==.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename R = void, class TList = NullType,
|
template <typename R = void, class TList = NullType,
|
||||||
template<class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>
|
template<class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>
|
||||||
|
@ -1239,6 +1314,34 @@ namespace Loki
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
|
||||||
|
bool isMemberFuncPtr() const
|
||||||
|
{
|
||||||
|
if(spImpl_.get()!=0)
|
||||||
|
return spImpl_.get()->isMemberFuncPtr();
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Functor& rhs) const
|
||||||
|
{
|
||||||
|
if(spImpl_.get()==0 && rhs.spImpl_.get()==0)
|
||||||
|
return true;
|
||||||
|
if(spImpl_.get()!=0 && rhs.spImpl_.get()!=0)
|
||||||
|
return *spImpl_.get() == *rhs.spImpl_.get();
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Functor& rhs) const
|
||||||
|
{
|
||||||
|
return !(*this==rhs);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// operator() implementations for up to 15 arguments
|
||||||
|
|
||||||
ResultType operator()() const
|
ResultType operator()() const
|
||||||
{
|
{
|
||||||
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
|
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
|
||||||
|
@ -1357,6 +1460,13 @@ namespace Loki
|
||||||
std::auto_ptr<Impl> spImpl_;
|
std::auto_ptr<Impl> spImpl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// BindersFirst and Chainer
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace Private
|
namespace Private
|
||||||
{
|
{
|
||||||
template <class Fctor> struct BinderFirstTraits;
|
template <class Fctor> struct BinderFirstTraits;
|
||||||
|
@ -1444,6 +1554,29 @@ namespace Loki
|
||||||
|
|
||||||
LOKI_DEFINE_CLONE_FUNCTORIMPL(BinderFirst)
|
LOKI_DEFINE_CLONE_FUNCTORIMPL(BinderFirst)
|
||||||
|
|
||||||
|
#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
|
||||||
|
bool isMemberFuncPtr() const
|
||||||
|
{
|
||||||
|
return f_.isMemberFuncPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const typename Base::FunctorImplBaseType& rhs) const
|
||||||
|
{
|
||||||
|
isMemberFuncPtr();
|
||||||
|
// if this line gives a compiler error, you are using a function object.
|
||||||
|
// you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
|
||||||
|
#ifdef LOKI_FUNCTOR_DEBUG
|
||||||
|
return f_ == ((dynamic_cast<const BinderFirst&> (rhs)).f_) &&
|
||||||
|
b_ == ((dynamic_cast<const BinderFirst&> (rhs)).b_);
|
||||||
|
|
||||||
|
#else
|
||||||
|
return f_ == ((static_cast<const BinderFirst&> (rhs)).f_) &&
|
||||||
|
b_ == ((static_cast<const BinderFirst&> (rhs)).b_);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// operator() implementations for up to 15 arguments
|
// operator() implementations for up to 15 arguments
|
||||||
|
|
||||||
ResultType operator()()
|
ResultType operator()()
|
||||||
|
@ -1563,6 +1696,29 @@ namespace Loki
|
||||||
|
|
||||||
LOKI_DEFINE_CLONE_FUNCTORIMPL(Chainer)
|
LOKI_DEFINE_CLONE_FUNCTORIMPL(Chainer)
|
||||||
|
|
||||||
|
#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
|
||||||
|
bool isMemberFuncPtr() const
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const typename Base::Impl::FunctorImplBaseType& rhs) const
|
||||||
|
{
|
||||||
|
// if this line gives a compiler error, you are using a function object.
|
||||||
|
// you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
|
||||||
|
#ifdef LOKI_FUNCTOR_DEBUG
|
||||||
|
return f1_ == ((dynamic_cast<const Chainer&> (rhs)).f2_) &&
|
||||||
|
f2_ == ((dynamic_cast<const Chainer&> (rhs)).f1_);
|
||||||
|
|
||||||
|
#else
|
||||||
|
return f1_ == ((static_cast<const Chainer&> (rhs)).f2_) &&
|
||||||
|
f2_ == ((static_cast<const Chainer&> (rhs)).f1_);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// operator() implementations for up to 15 arguments
|
// operator() implementations for up to 15 arguments
|
||||||
|
|
||||||
ResultType operator()()
|
ResultType operator()()
|
||||||
|
@ -1689,6 +1845,9 @@ namespace Loki
|
||||||
#endif // FUNCTOR_INC_
|
#endif // FUNCTOR_INC_
|
||||||
|
|
||||||
// $Log$
|
// $Log$
|
||||||
|
// Revision 1.21 2006/06/01 12:33:05 syntheticpp
|
||||||
|
// add operator== to Functor, initiated by Eric Beyeler
|
||||||
|
//
|
||||||
// Revision 1.20 2006/05/20 10:23:07 syntheticpp
|
// Revision 1.20 2006/05/20 10:23:07 syntheticpp
|
||||||
// add warnings in the documentation about the special lifetime when using SmallObjects
|
// add warnings in the documentation about the special lifetime when using SmallObjects
|
||||||
//
|
//
|
||||||
|
|
|
@ -2,16 +2,18 @@
|
||||||
// Unit Test for Loki
|
// Unit Test for Loki
|
||||||
//
|
//
|
||||||
// Copyright Terje Slettebø and Pavel Vozenilek 2002.
|
// Copyright Terje Slettebø and Pavel Vozenilek 2002.
|
||||||
//
|
// Copyright Peter Kümmel, 2006
|
||||||
|
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose is hereby granted without fee, provided that this copyright and
|
// purpose is hereby granted without fee, provided that this copyright and
|
||||||
// permissions notice appear in all copies and derivatives.
|
// permissions notice appear in all copies and derivatives.
|
||||||
//
|
//
|
||||||
// This software is provided "as is" without express or implied warranty.
|
// This software is provided "as is" without express or implied warranty.
|
||||||
//
|
//
|
||||||
// Last update: September 16, 2002
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// $Header:
|
||||||
|
|
||||||
#ifndef FUNCTORTEST_H
|
#ifndef FUNCTORTEST_H
|
||||||
#define FUNCTORTEST_H
|
#define FUNCTORTEST_H
|
||||||
|
|
||||||
|
@ -21,6 +23,11 @@
|
||||||
// FunctorTest
|
// FunctorTest
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void free_function(bool &result)
|
||||||
|
{
|
||||||
|
result=true;
|
||||||
|
}
|
||||||
|
|
||||||
class FunctorTest : public Test
|
class FunctorTest : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -40,16 +47,33 @@ public:
|
||||||
|
|
||||||
#ifndef LOKI_DISABLE_TYPELIST_MACROS
|
#ifndef LOKI_DISABLE_TYPELIST_MACROS
|
||||||
Functor<void,LOKI_TYPELIST_1(bool &)> function(testFunction);
|
Functor<void,LOKI_TYPELIST_1(bool &)> function(testFunction);
|
||||||
|
Functor<void,LOKI_TYPELIST_1(bool &)> function2(testFunction);
|
||||||
Functor<void,LOKI_TYPELIST_1(bool &)> functor(testFunctor);
|
Functor<void,LOKI_TYPELIST_1(bool &)> functor(testFunctor);
|
||||||
|
Functor<void,LOKI_TYPELIST_1(bool &)> functor2(testFunctor);
|
||||||
Functor<void,LOKI_TYPELIST_1(bool &)> classFunctor(&testClass,&TestClass::member);
|
Functor<void,LOKI_TYPELIST_1(bool &)> classFunctor(&testClass,&TestClass::member);
|
||||||
|
Functor<void,LOKI_TYPELIST_1(bool &)> classFunctor2(&testClass,&TestClass::member);
|
||||||
Functor<void,LOKI_TYPELIST_1(bool &)> functorCopy(function);
|
Functor<void,LOKI_TYPELIST_1(bool &)> functorCopy(function);
|
||||||
|
Functor<void,LOKI_TYPELIST_1(bool &)> functorCopy2(function);
|
||||||
|
|
||||||
Functor<void,NullType> bindFunctor(BindFirst(function,testResult));
|
Functor<void,NullType> bindFunctor(BindFirst(function,testResult));
|
||||||
|
Functor<void,NullType> bindFunctor2(BindFirst(function,testResult));
|
||||||
|
|
||||||
Functor<void> chainFunctor(Chain(bindFunctor,bindFunctor));
|
Functor<void> chainFunctor(Chain(bindFunctor,bindFunctor));
|
||||||
|
Functor<void> chainFunctor2(Chain(bindFunctor,bindFunctor));
|
||||||
|
|
||||||
|
Functor<void,LOKI_TYPELIST_1(bool &)> member_func(&testClass,&TestClass::member);
|
||||||
|
Functor<void,LOKI_TYPELIST_1(bool &)> free_func(&free_function);
|
||||||
|
Functor<void,LOKI_TYPELIST_1(bool &)> NULL_func;
|
||||||
|
Functor<void,LOKI_TYPELIST_1(bool &)> NULL_func0;
|
||||||
#else
|
#else
|
||||||
Functor<void,Seq<bool &> > function(testFunction);
|
Functor<void,Seq<bool &> > function(testFunction);
|
||||||
|
Functor<void,Seq<bool &> > function2(testFunction);
|
||||||
Functor<void,Seq<bool &> > functor(testFunctor);
|
Functor<void,Seq<bool &> > functor(testFunctor);
|
||||||
|
Functor<void,Seq<bool &> > functor2(testFunctor);
|
||||||
Functor<void,Seq<bool &> > classFunctor(&testClass,&TestClass::member);
|
Functor<void,Seq<bool &> > classFunctor(&testClass,&TestClass::member);
|
||||||
|
Functor<void,Seq<bool &> > classFunctor2(&testClass,&TestClass::member);
|
||||||
Functor<void,Seq<bool &> > functorCopy(function);
|
Functor<void,Seq<bool &> > functorCopy(function);
|
||||||
|
Functor<void,Seq<bool &> > functorCopy2(function);
|
||||||
//TODO:
|
//TODO:
|
||||||
//Functor<void,NullType> bindFunctor(BindFirst(function,testResult));
|
//Functor<void,NullType> bindFunctor(BindFirst(function,testResult));
|
||||||
//Functor<void> chainFunctor(Chain(bindFunctor,bindFunctor));
|
//Functor<void> chainFunctor(Chain(bindFunctor,bindFunctor));
|
||||||
|
@ -71,7 +95,52 @@ public:
|
||||||
functorCopy(testResult);
|
functorCopy(testResult);
|
||||||
bool functorCopyResult=testResult;
|
bool functorCopyResult=testResult;
|
||||||
|
|
||||||
|
#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
|
||||||
|
bool functionCompare = function==function2;
|
||||||
|
bool functorCompare = functor!=functor2; // is this a bug?
|
||||||
|
bool classFunctorCompare = classFunctor==classFunctor2;
|
||||||
|
bool functorCopyCompare = functorCopy==functorCopy2;
|
||||||
|
|
||||||
|
bool free_mem = free_func!=member_func;
|
||||||
|
bool mem_free = member_func!=free_func;
|
||||||
|
|
||||||
|
bool null0 = NULL_func == NULL_func0;
|
||||||
|
bool null1 = NULL_func != free_func;
|
||||||
|
bool null2 = NULL_func != member_func;
|
||||||
|
bool null3 = free_func != NULL_func;
|
||||||
|
bool null4 = member_func != NULL_func;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LOKI_DISABLE_TYPELIST_MACROS
|
||||||
|
bool bindFunctorCompare = bindFunctor==bindFunctor2;
|
||||||
|
bool chainFunctorCompare = chainFunctor==chainFunctor2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool compare = functionCompare &&
|
||||||
|
functorCompare &&
|
||||||
|
classFunctorCompare &&
|
||||||
|
functorCopyCompare &&
|
||||||
|
mem_free &&
|
||||||
|
free_mem &&
|
||||||
|
null0 &&
|
||||||
|
null1 &&
|
||||||
|
null2 &&
|
||||||
|
null3 &&
|
||||||
|
null4
|
||||||
#ifndef LOKI_DISABLE_TYPELIST_MACROS
|
#ifndef LOKI_DISABLE_TYPELIST_MACROS
|
||||||
|
;
|
||||||
|
#else
|
||||||
|
&& bindFunctorCompare
|
||||||
|
&& chainFunctorCompare;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
bool compare=true;
|
||||||
|
#endif //LOKI_FUNCTORS_ARE_COMPARABLE
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LOKI_DISABLE_TYPELIST_MACROS
|
||||||
testResult=false;
|
testResult=false;
|
||||||
bindFunctor();
|
bindFunctor();
|
||||||
bool bindFunctorResult=testResult;
|
bool bindFunctorResult=testResult;
|
||||||
|
@ -81,12 +150,11 @@ public:
|
||||||
bool chainFunctorResult=testResult;
|
bool chainFunctorResult=testResult;
|
||||||
|
|
||||||
r=functionResult && functorResult && classFunctorResult && functorCopyResult && bindFunctorResult &&
|
r=functionResult && functorResult && classFunctorResult && functorCopyResult && bindFunctorResult &&
|
||||||
chainFunctorResult;
|
chainFunctorResult && compare;
|
||||||
#else
|
#else
|
||||||
//TODO!
|
//TODO!
|
||||||
r=functionResult && functorResult && classFunctorResult && functorCopyResult;
|
r=functionResult && functorResult && classFunctorResult && functorCopyResult && compare;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
testAssert("Functor",r,result);
|
testAssert("Functor",r,result);
|
||||||
|
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
|
@ -107,6 +175,11 @@ private:
|
||||||
{
|
{
|
||||||
result=true;
|
result=true;
|
||||||
}
|
}
|
||||||
|
bool operator==(const TestFunctor& rhs) const
|
||||||
|
{
|
||||||
|
const TestFunctor* p = &rhs;
|
||||||
|
return this==p;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestClass
|
class TestClass
|
||||||
|
@ -123,6 +196,6 @@ bool FunctorTest::testResult;
|
||||||
|
|
||||||
#ifndef SMALLOBJ_CPP
|
#ifndef SMALLOBJ_CPP
|
||||||
# define SMALLOBJ_CPP
|
# define SMALLOBJ_CPP
|
||||||
# include "../../SmallObj.cpp"
|
# include "../../src/SmallObj.cpp"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue