add boost/TR1 like usage of Functor, with a test program from boost 1.33

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@320 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
syntheticpp 2005-10-24 15:40:22 +00:00
parent b73fe0bbcf
commit da979a7e0e
4 changed files with 1295 additions and 14 deletions

337
include/loki/Function.h Executable file
View file

@ -0,0 +1,337 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2005 Peter Kümmel
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author makes no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
#define LOKI_ENABLE_FUNCTION
#include <loki/Functor.h>
#include <loki/Sequence.h>
namespace Loki
{
template<class R>
struct Function;
////////////////////////////////////////////////////////////////////////////////
// Function allows a boost/TR1 like usage of Functor.
//
// e.g. Functor<int,LOKI_TYPELIST_2(int,int)> becomes Function<int(int,int)>
////////////////////////////////////////////////////////////////////////////////
template<class R>
struct Function<R()> : public Functor<R>
{
typedef Functor<R> FBase;
Function() : FBase() {}
Function(const Function& func) : FBase()
{
if( !func.empty())
FBase::operator=(func);
}
// emptiness
template<class R2>
Function(Function<R2()> func) : FBase()
{
if(!func.empty())
FBase::operator=(func);
}
// clear by '= 0'
Function(const int i) : FBase()
{
if(i==0)
FBase::clear();
else
throw std::runtime_error("Loki::Function(const int i): i!=0");
}
template<class Func>
Function(Func func) : FBase(func) {}
template<class Host, class Func>
Function(const Host& host, const Func& func) : FBase(host,func) {}
};
////////////////////////////////////////////////////////////////////////////////
// macros for the repetitions
////////////////////////////////////////////////////////////////////////////////
#define LOKI_FUNCTION_BODY \
\
Function() : FBase() {} \
\
Function(const Function& func) : FBase() \
{ \
if( !func.empty()) \
FBase::operator=(func); \
} \
\
Function(const int i) : FBase() \
{ \
if(i==0) \
FBase::clear(); \
else \
throw std::runtime_error( \
"Loki::Function(const int i): i!=0"); \
} \
\
template<class Func> \
Function(Func func) : FBase(func) {} \
\
template<class Host, class Func> \
Function(const Host& host, const Func& func): FBase(host,func) {}
#define LOKI_FUNCTION_R2_CTOR_BODY \
\
: FBase() \
{ \
if(!func.empty()) \
FBase::operator=(func); \
}
////////////////////////////////////////////////////////////////////////////////
// repetitions
////////////////////////////////////////////////////////////////////////////////
template<class R,class P01>
struct Function<R(P01)>
: public Loki::Functor<R,typename Seq<P01>::Type>
{
typedef Functor<R,typename Seq<P01>::Type> FBase;
template<class R2,class Q01>
Function(Function<R2(Q01)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R,class P01,class P02>
struct Function<R(P01,P02)>
: public Functor<R,typename Seq<P01,P02>::Type>
{
typedef Functor<R,typename Seq<P01,P02>::Type> FBase;
template<class R2,class Q01, class Q02>
Function(Function<R2(Q01,Q02)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R,class P01,class P02, class P03>
struct Function<R(P01,P02,P03)>
: public Functor<R,typename Seq<P01,P02,P03>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03>::Type> FBase;
template<class R2,class Q01, class Q02,class Q03>
Function(Function<R2(Q01,Q02,Q03)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R,class P01,class P02, class P03,class P04>
struct Function<R(P01,P02,P03,P04)>
: public Functor<R,typename Seq<P01,P02,P03,P04>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04>::Type> FBase;
template<class R2,class Q01,class Q02, class Q03,class Q04>
Function(Function<R2(Q01,Q02,Q03,Q04)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R,class P01,class P02, class P03,class P04,class P05>
struct Function<R(P01,P02,P03,P04,P05)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05>::Type> FBase;
template<class R2,class Q01,class Q02, class Q03,class Q04,class Q05>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06>
struct Function<R(P01,P02,P03,P04,P05,P06)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06>::Type> FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06,class P07>
struct Function<R(P01,P02,P03,P04,P05,P06,P07)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07>::Type> FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06,class Q07>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06,class P07, class P08>
struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08>::Type> FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06,class Q07, class Q08>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06,class P07, class P08,class P09>
struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09 >::Type> FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06,class Q07, class Q08,class Q09>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06,class P07, class P08,class P09,class P10>
struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10>::Type> FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06,class Q07, class Q08,class Q09,class Q10>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06,class P07, class P08,class P09,class P10,
class P11>
struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11>::Type>FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06,class Q07, class Q08,class Q09,class Q10,
class Q11>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06,class P07, class P08,class P09,class P10,
class P11,class P12>
struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12>::Type> FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06,class Q07, class Q08,class Q09,class Q10,
class Q11,class Q12>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06,class P07, class P08,class P09,class P10,
class P11,class P12, class P13>
struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13>::Type> FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06,class Q07, class Q08,class Q09,class Q10,
class Q11,class Q12, class Q13>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12,Q13)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06,class P07, class P08,class P09,class P10,
class P11,class P12, class P13,class P14>
struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14>::Type> FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06,class Q07, class Q08,class Q09,class Q10,
class Q11,class Q12, class Q13,class Q14>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12,Q13,Q14)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
template<class R, class P01,class P02, class P03,class P04,class P05,
class P06,class P07, class P08,class P09,class P10,
class P11,class P12, class P13,class P14,class P15>
struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14,P15)>
: public Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14,P15>::Type>
{
typedef Functor<R,typename Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14,P15>::Type> FBase;
template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
class Q06,class Q07, class Q08,class Q09,class Q10,
class Q11,class Q12, class Q13,class Q14,class Q15>
Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12,Q13,Q14,Q15)> func)
LOKI_FUNCTION_R2_CTOR_BODY
LOKI_FUNCTION_BODY
};
}// namespace Loki

View file

@ -714,11 +714,31 @@ namespace Loki
PointerToMemFn pMemFn_; PointerToMemFn pMemFn_;
}; };
////////////////////////////////////////////////////////////////////////////////
// TR1 exception
//////////////////////////////////////////////////////////////////////////////////
#ifdef LOKI_ENABLE_FUNCTION
class bad_function_call : public std::runtime_error
{
public:
bad_function_call() : std::runtime_error("bad_function_call in Loki::Functor")
{}
};
#define LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL if(empty()) throw bad_function_call();
#else
#define LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template Functor // class template Functor
// A generalized functor implementation with value semantics // A generalized functor implementation with value semantics
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename R, class TList = NullType, template <typename R, class TList = NullType,
template<class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL> template<class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>
class Functor class Functor
@ -782,52 +802,102 @@ namespace Loki
return *this; return *this;
} }
#ifdef LOKI_ENABLE_FUNCTION
bool empty() const
{
return spImpl_.get() == 0;
}
void clear()
{
spImpl_.reset(0);
}
#endif
ResultType operator()() const ResultType operator()() const
{ return (*spImpl_)(); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)();
}
ResultType operator()(Parm1 p1) const ResultType operator()(Parm1 p1) const
{ return (*spImpl_)(p1); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1);
}
ResultType operator()(Parm1 p1, Parm2 p2) const ResultType operator()(Parm1 p1, Parm2 p2) const
{ return (*spImpl_)(p1, p2); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) const ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) const
{ return (*spImpl_)(p1, p2, p3); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) const ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) const
{ return (*spImpl_)(p1, p2, p3, p4); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) const ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) const
{ return (*spImpl_)(p1, p2, p3, p4, p5); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
Parm6 p6) const Parm6 p6) const
{ return (*spImpl_)(p1, p2, p3, p4, p5, p6); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
Parm6 p6, Parm7 p7) const Parm6 p6, Parm7 p7) const
{ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
Parm6 p6, Parm7 p7, Parm8 p8) const Parm6 p6, Parm7 p7, Parm8 p8) const
{ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) const Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) const
{ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) const Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) const
{ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) const Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) const
{ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
}
ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
Parm12 p12) const Parm12 p12) const
{ {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
p12); p12);
} }
@ -836,6 +906,7 @@ namespace Loki
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
Parm12 p12, Parm13 p13) const Parm12 p12, Parm13 p13) const
{ {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
p12, p13); p12, p13);
} }
@ -844,6 +915,7 @@ namespace Loki
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
Parm12 p12, Parm13 p13, Parm14 p14) const Parm12 p12, Parm13 p13, Parm14 p14) const
{ {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
p12, p13, p14); p12, p13, p14);
} }
@ -852,6 +924,7 @@ namespace Loki
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) const Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) const
{ {
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
p12, p13, p14, p15); p12, p13, p14, p15);
} }

792
test/Function/FunctionTest.cpp Executable file
View file

@ -0,0 +1,792 @@
// Boost.Function library
// Copyright Douglas Gregor 2001-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org
#include <functional>
#include <cassert>
#include <string>
#include <utility>
#include <boost/test/minimal.hpp>
#define TEST_LOKI_FUNCTION
#ifndef TEST_LOKI_FUNCTION
#include <boost/function.hpp>
using namespace boost;
#else
#include <boost/ref.hpp>
#include <loki/Function.h>
using namespace Loki;
#define BOOST_FUNCTION_TARGET_FIX(x) x
#define function Function
#endif
using namespace std;
int global_int;
struct write_five_obj{void operator()() const {global_int = 5;}};
#ifndef TEST_LOKI_FUNCTION
struct write_three_obj{int operator()() const {global_int = 3; return 7;}};
#else
struct write_three_obj{void operator()() const {global_int = 3;}};
#endif
static void write_five() {global_int = 5;}
static void write_three() {global_int = 3;}
struct generate_five_obj {int operator()() const {return 5;}};
struct generate_three_obj {int operator()() const {return 3;}};
static int generate_five() {return 5;}
static int generate_three() {return 3;}
static string identity_str(const string& s){return s;}
static string string_cat(const string& s1, const string& s2){return s1+s2;}
static int sum_ints(int x, int y){return x+y;}
struct write_const_1_nonconst_2
{
void operator()(){global_int = 2;}
void operator()() const {global_int = 1;}
};
struct add_to_obj
{
add_to_obj(int v) : value(v) {}
int operator()(int x) const {return value + x;}
int value;
};
static void test_zero_args()
{
typedef function<void ()> func_void_type;
write_five_obj five;
write_three_obj three;
// Default construction
func_void_type v1;
BOOST_CHECK(v1.empty());
// Assignment to an empty function
v1 = five;
BOOST_CHECK(v1 != 0);
// Invocation of a function
global_int = 0;
v1();
BOOST_CHECK(global_int == 5);
// clear() method
v1.clear();
BOOST_CHECK(v1 == 0);
// Assignment to an empty function
v1 = three;
BOOST_CHECK(!v1.empty());
// Invocation and self-assignment
global_int = 0;
v1 = v1;
v1();
BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function
v1 = five;
// Invocation and self-assignment
global_int = 0;
v1 = (v1);
v1();
BOOST_CHECK(global_int == 5);
// clear
v1 = 0;
BOOST_CHECK(0 == v1);
// Assignment to an empty function from a free function
v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
BOOST_CHECK(0 != v1);
// Invocation
global_int = 0;
v1();
BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function
v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
BOOST_CHECK(!v1.empty());
// Invocation
global_int = 0;
v1();
BOOST_CHECK(global_int == 3);
// Assignment
v1 = five;
BOOST_CHECK(!v1.empty());
// Invocation
global_int = 0;
v1();
BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function
v1 = &write_three;
BOOST_CHECK(!v1.empty());
// Invocation
global_int = 0;
v1();
BOOST_CHECK(global_int == 3);
// Construction from another function (that is empty)
v1.clear();
func_void_type v2(v1);
BOOST_CHECK(!v2? true : false);
// Assignment to an empty function
v2 = three;
BOOST_CHECK(!v2.empty());
// Invocation
global_int = 0;
v2();
BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function
v2 = (five);
// Invocation
global_int = 0;
v2();
BOOST_CHECK(global_int == 5);
v2.clear();
BOOST_CHECK(v2.empty());
// Assignment to an empty function from a free function
v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five);
BOOST_CHECK(v2? true : false);
// Invocation
global_int = 0;
v2();
BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function
v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
BOOST_CHECK(!v2.empty());
// Invocation
global_int = 0;
v2();
BOOST_CHECK(global_int == 3);
// Swapping
v1 = five;
swap(v1, v2);
v2();
BOOST_CHECK(global_int == 5);
v1();
BOOST_CHECK(global_int == 3);
swap(v1, v2);
v1.clear();
// Assignment
v2 = five;
BOOST_CHECK(!v2.empty());
// Invocation
global_int = 0;
v2();
BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function
v2 = &write_three;
BOOST_CHECK(!v2.empty());
// Invocation
global_int = 0;
v2();
BOOST_CHECK(global_int == 3);
// Assignment to a function from an empty function
v2 = v1;
BOOST_CHECK(v2.empty());
// Assignment to a function from a function with a functor
v1 = three;
v2 = v1;
BOOST_CHECK(!v1.empty());
BOOST_CHECK(!v2.empty());
// Invocation
global_int = 0;
v1();
BOOST_CHECK(global_int == 3);
global_int = 0;
v2();
BOOST_CHECK(global_int == 3);
// Assign to a function from a function with a function
v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
v1 = v2;
BOOST_CHECK(!v1.empty());
BOOST_CHECK(!v2.empty());
global_int = 0;
v1();
BOOST_CHECK(global_int == 5);
global_int = 0;
v2();
BOOST_CHECK(global_int == 5);
// Construct a function given another function containing a function
func_void_type v3(v1);
// Invocation of a function
global_int = 0;
v3();
BOOST_CHECK(global_int == 5);
// clear() method
v3.clear();
BOOST_CHECK(!v3? true : false);
// Assignment to an empty function
v3 = three;
BOOST_CHECK(!v3.empty());
// Invocation
global_int = 0;
v3();
BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function
v3 = five;
// Invocation
global_int = 0;
v3();
BOOST_CHECK(global_int == 5);
// clear()
v3.clear();
BOOST_CHECK(v3.empty());
// Assignment to an empty function from a free function
v3 = &write_five;
BOOST_CHECK(!v3.empty());
// Invocation
global_int = 0;
v3();
BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function
v3 = &write_three;
BOOST_CHECK(!v3.empty());
// Invocation
global_int = 0;
v3();
BOOST_CHECK(global_int == 3);
// Assignment
v3 = five;
BOOST_CHECK(!v3.empty());
// Invocation
global_int = 0;
v3();
BOOST_CHECK(global_int == 5);
// Construction of a function from a function containing a functor
func_void_type v4(v3);
// Invocation of a function
global_int = 0;
v4();
BOOST_CHECK(global_int == 5);
// clear() method
v4.clear();
BOOST_CHECK(v4.empty());
// Assignment to an empty function
v4 = three;
BOOST_CHECK(!v4.empty());
// Invocation
global_int = 0;
v4();
BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function
v4 = five;
// Invocation
global_int = 0;
v4();
BOOST_CHECK(global_int == 5);
// clear()
v4.clear();
BOOST_CHECK(v4.empty());
// Assignment to an empty function from a free function
v4 = &write_five;
BOOST_CHECK(!v4.empty());
// Invocation
global_int = 0;
v4();
BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function
v4 = &write_three;
BOOST_CHECK(!v4.empty());
// Invocation
global_int = 0;
v4();
BOOST_CHECK(global_int == 3);
// Assignment
v4 = five;
BOOST_CHECK(!v4.empty());
// Invocation
global_int = 0;
v4();
BOOST_CHECK(global_int == 5);
// Construction of a function from a functor
func_void_type v5(five);
// Invocation of a function
global_int = 0;
v5();
BOOST_CHECK(global_int == 5);
// clear() method
v5.clear();
BOOST_CHECK(v5.empty());
// Assignment to an empty function
v5 = three;
BOOST_CHECK(!v5.empty());
// Invocation
global_int = 0;
v5();
BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function
v5 = five;
// Invocation
global_int = 0;
v5();
BOOST_CHECK(global_int == 5);
// clear()
v5.clear();
BOOST_CHECK(v5.empty());
// Assignment to an empty function from a free function
v5 = &write_five;
BOOST_CHECK(!v5.empty());
// Invocation
global_int = 0;
v5();
BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function
v5 = &write_three;
BOOST_CHECK(!v5.empty());
// Invocation
global_int = 0;
v5();
BOOST_CHECK(global_int == 3);
// Assignment
v5 = five;
BOOST_CHECK(!v5.empty());
// Invocation
global_int = 0;
v5();
BOOST_CHECK(global_int == 5);
// Construction of a function from a function
func_void_type v6(&write_five);
// Invocation of a function
global_int = 0;
v6();
BOOST_CHECK(global_int == 5);
// clear() method
v6.clear();
BOOST_CHECK(v6.empty());
// Assignment to an empty function
v6 = three;
BOOST_CHECK(!v6.empty());
// Invocation
global_int = 0;
v6();
BOOST_CHECK(global_int == 3);
// Assignment to a non-empty function
v6 = five;
// Invocation
global_int = 0;
v6();
BOOST_CHECK(global_int == 5);
// clear()
v6.clear();
BOOST_CHECK(v6.empty());
// Assignment to an empty function from a free function
v6 = &write_five;
BOOST_CHECK(!v6.empty());
// Invocation
global_int = 0;
v6();
BOOST_CHECK(global_int == 5);
// Assignment to a non-empty function from a free function
v6 = &write_three;
BOOST_CHECK(!v6.empty());
// Invocation
global_int = 0;
v6();
BOOST_CHECK(global_int == 3);
// Assignment
v6 = five;
BOOST_CHECK(!v6.empty());
// Invocation
global_int = 0;
v6();
BOOST_CHECK(global_int == 5);
// Const vs. non-const
write_const_1_nonconst_2 one_or_two;
const function<void ()> v7(one_or_two);
function<void ()> v8(one_or_two);
global_int = 0;
v7();
BOOST_CHECK(global_int == 2);
global_int = 0;
v8();
BOOST_CHECK(global_int == 2);
// Test construction from 0 and comparison to 0
func_void_type v9(0);
BOOST_CHECK(v9 == 0);
BOOST_CHECK(0 == v9);
// Test return values
typedef function<int ()> func_int_type;
generate_five_obj gen_five;
generate_three_obj gen_three;
func_int_type i0(gen_five);
BOOST_CHECK(i0() == 5);
i0 = gen_three;
BOOST_CHECK(i0() == 3);
i0 = &generate_five;
BOOST_CHECK(i0() == 5);
i0 = &generate_three;
BOOST_CHECK(i0() == 3);
BOOST_CHECK(i0? true : false);
i0.clear();
BOOST_CHECK(!i0? true : false);
// Test return values with compatible types
typedef function<long ()> func_long_type;
func_long_type i1(gen_five);
BOOST_CHECK(i1() == 5);
i1 = gen_three;
BOOST_CHECK(i1() == 3);
i1 = &generate_five;
BOOST_CHECK(i1() == 5);
i1 = &generate_three;
BOOST_CHECK(i1() == 3);
BOOST_CHECK(i1? true : false);
i1.clear();
BOOST_CHECK(!i1? true : false);
}
static void test_one_arg()
{
negate<int> neg;
function<int (int)> f1(neg);
BOOST_CHECK(f1(5) == -5);
function<string (string)> id(&identity_str);
BOOST_CHECK(id("str") == "str");
function<string (const char*)> id2(&identity_str);
BOOST_CHECK(id2("foo") == "foo");
add_to_obj add_to(5);
function<int (int)> f2(add_to);
BOOST_CHECK(f2(3) == 8);
const function<int (int)> cf2(add_to);
BOOST_CHECK(cf2(3) == 8);
}
static void test_two_args()
{
function<string (const string&, const string&)> cat(&string_cat);
BOOST_CHECK(cat("str", "ing") == "string");
function<int (short, short)> sum(&sum_ints);
BOOST_CHECK(sum(2, 3) == 5);
}
static void test_emptiness()
{
function<float ()> f1;
BOOST_CHECK(f1.empty());
function<float ()> f2;
f2 = f1;
BOOST_CHECK(f2.empty());
function<double ()> f3;
f3 = f2;
BOOST_CHECK(f3.empty());
}
struct X
{
X(int v) : value(v)
{}
int twice() const
{
return 2*value;
}
int plus(int v)
{
return value + v;
}
int value;
};
static void test_member_functions()
{
#ifndef TEST_LOKI_FUNCTION
boost::function<int (X*)> f1(&X::twice);
X one(1);
X five(5);
BOOST_CHECK(f1(&one) == 2);
BOOST_CHECK(f1(&five) == 10);
#else
X one(1);
X five(5);
Loki::Function<int()> f1(&one,&X::twice);
BOOST_CHECK(f1() == 2);
f1 = Loki::Function<int()>(&five,&X::twice);
BOOST_CHECK(f1() == 10);
#endif
#ifndef TEST_LOKI_FUNCTION
boost::function<int (X*)> f1_2;
f1_2 = &X::twice;
BOOST_CHECK(f1_2(&one) == 2);
BOOST_CHECK(f1_2(&five) == 10);
#else
Loki::Function<int ()> f1_2(&one,&X::twice);
BOOST_CHECK(f1_2() == 2);
f1_2 = Loki::function<int ()>(&five,&X::twice);
BOOST_CHECK(f1_2() == 10);
#endif
#ifndef TEST_LOKI_FUNCTION
boost::function<int (X&, int)> f2(&X::plus);
BOOST_CHECK(f2(one, 3) == 4);
BOOST_CHECK(f2(five, 4) == 9);
#else
Loki::Function<int (int)> f2(&one,&X::plus);
BOOST_CHECK(f2(3) == 4);
f2 = Loki::Function<int (int)>(&five,&X::plus);
BOOST_CHECK(f2(4) == 9);
#endif
}
struct add_with_throw_on_copy
{
int operator()(int x, int y) const
{
return x+y;
}
add_with_throw_on_copy()
{}
add_with_throw_on_copy(const add_with_throw_on_copy&)
{
throw runtime_error("But this CAN'T throw");
}
add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
{
throw runtime_error("But this CAN'T throw");
}
};
static void test_ref()
{
add_with_throw_on_copy atc;
try
{
#ifndef TEST_LOKI_FUNCTION
boost::function<int (int, int)> f(ref(atc));
BOOST_CHECK(f(1, 3) == 4);
#else
//TODO: implement Loki::Ref
//Loki::Function<int (int, int)> f(Loki::ref(atc));
//BOOST_CHECK(f(1, 3) == 4);
#endif
}
catch(runtime_error e)
{
BOOST_ERROR("Nonthrowing constructor threw an exception");
}
}
static void test_exception()
{
#ifndef TEST_LOKI_FUNCTION
boost::function<int (int, int)> f;
#else
Loki::Function<int (int, int)> f;
#endif
try
{
f(5, 4);
BOOST_CHECK(false);
}
#ifndef TEST_LOKI_FUNCTION
catch(boost::bad_function_call)
#else
catch(Loki::bad_function_call)
#endif
{
// okay
}
}
#ifndef TEST_LOKI_FUNCTION
typedef boost::function< void * (void * reader) > reader_type;
#else
typedef Loki::Function< void * (void * reader) > reader_type;
#endif
typedef std::pair<int, reader_type> mapped_type;
static void test_implicit()
{
mapped_type m;
m = mapped_type();
}
#ifndef TEST_LOKI_FUNCTION
static void test_call_obj(boost::function<int (int, int)> f)
#else
static void test_call_obj(Loki::function<int (int, int)> f)
#endif
{
assert(!f.empty());
}
#ifndef TEST_LOKI_FUNCTION
static void test_call_cref(const boost::function<int (int, int)>& f)
#else
static void test_call_cref(const Loki::Function<int (int, int)>& f)
#endif
{
assert(!f.empty());
}
static void test_call()
{
test_call_obj(std::plus<int>());
test_call_cref(std::plus<int>());
}
int test_main(int, char* [])
{
test_zero_args();
test_one_arg();
test_two_args();
test_emptiness();
test_member_functions();
test_ref();
test_exception();
test_implicit();
test_call();
system("pause");
return 0;
}

79
test/Function/FunctionTest.dev Executable file
View file

@ -0,0 +1,79 @@
[Project]
FileName=FunctionTest.dev
Name=FunctionTest
UnitCount=3
Type=1
Ver=1
ObjFiles=
Includes=..\..\include;..;.
Libs=
PrivateResource=
ResourceIncludes=
MakeIncludes=
Compiler=
CppCompiler=-Wall -pedantic_@@_
Linker=
IsCpp=1
Icon=
ExeOutput=
ObjectOutput=
OverrideOutput=0
OverrideOutputName=FunctionTest.exe
HostApplication=
Folders=
CommandLine=
UseCustomMakefile=0
CustomMakefile=Makefile.loki
IncludeVersionInfo=0
SupportXPThemes=0
CompilerSet=0
CompilerSettings=0000000001010000000000
[VersionInfo]
Major=0
Minor=1
Release=1
Build=1
LanguageID=1033
CharsetID=1252
CompanyName=
FileVersion=
FileDescription=Developed using the Dev-C++ IDE
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=
ProductName=
ProductVersion=
AutoIncBuildNr=0
[Unit1]
FileName=..\..\src\Singleton.cpp
CompileCpp=1
Folder=FunctionTest
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit2]
FileName=..\..\src\SmallObj.cpp
CompileCpp=1
Folder=FunctionTest
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit3]
FileName=FunctionTest.cpp
CompileCpp=1
Folder=FunctionTest
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=