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_;
};
////////////////////////////////////////////////////////////////////////////////
// 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
// A generalized functor implementation with value semantics
////////////////////////////////////////////////////////////////////////////////
template <typename R, class TList = NullType,
template<class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>
class Functor
@ -781,53 +801,103 @@ namespace Loki
copy.spImpl_.reset(p);
return *this;
}
#ifdef LOKI_ENABLE_FUNCTION
bool empty() const
{
return spImpl_.get() == 0;
}
void clear()
{
spImpl_.reset(0);
}
#endif
ResultType operator()() const
{ return (*spImpl_)(); }
{
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)();
}
ResultType operator()(Parm1 p1) const
{ return (*spImpl_)(p1); }
{
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1);
}
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
{ 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
{ 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
{ 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,
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,
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,
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,
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,
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,
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,
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
Parm12 p12) const
{
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
p12);
}
@ -836,6 +906,7 @@ namespace Loki
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
Parm12 p12, Parm13 p13) const
{
LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
p12, p13);
}
@ -844,6 +915,7 @@ namespace Loki
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
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,
p12, p13, p14);
}
@ -852,6 +924,7 @@ namespace Loki
Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
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,
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=