mirror of
https://github.com/boostorg/function.git
synced 2025-07-17 06:32:13 +02:00
boost/function/function_template.hpp, boost/function/function_base.hpp:
- Added "contains" member function to extract a pointer to the target function object if you know its type - Added operator== that can compare a Boost.Function object against a function object libs/function/test/Jamfile, libs/function/test/contains_test.cpp: - Test contains() and equality comparison operators [SVN r21844]
This commit is contained in:
@ -14,17 +14,31 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <typeinfo>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/type_traits/arithmetic_traits.hpp>
|
#include <boost/type_traits/is_integral.hpp>
|
||||||
#include <boost/type_traits/composite_traits.hpp>
|
#include <boost/type_traits/composite_traits.hpp>
|
||||||
#include <boost/type_traits/is_stateless.hpp>
|
#include <boost/type_traits/is_stateless.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
#include <boost/pending/ct_if.hpp>
|
#include <boost/pending/ct_if.hpp>
|
||||||
#include <boost/detail/workaround.hpp>
|
#include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
#ifndef BOOST_NO_SFINAE
|
#ifndef BOOST_NO_SFINAE
|
||||||
# include "boost/utility/enable_if.hpp"
|
# include "boost/utility/enable_if.hpp"
|
||||||
|
#else
|
||||||
|
# include "boost/mpl/bool.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Borrowed from Boost.Python library: determines the cases where we
|
||||||
|
// need to use std::type_info::name to compare instead of operator==.
|
||||||
|
# if (defined(__GNUC__) && __GNUC__ >= 3) \
|
||||||
|
|| defined(_AIX) \
|
||||||
|
|| ( defined(__sgi) && defined(__host_mips))
|
||||||
|
# include <cstring>
|
||||||
|
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
|
||||||
|
(std::strcmp((X).name(),(Y).name()) == 0)
|
||||||
|
# else
|
||||||
|
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) (X==Y)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
|
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
|
||||||
@ -139,7 +153,8 @@ namespace boost {
|
|||||||
// The operation type to perform on the given functor/function pointer
|
// The operation type to perform on the given functor/function pointer
|
||||||
enum functor_manager_operation_type {
|
enum functor_manager_operation_type {
|
||||||
clone_functor_tag,
|
clone_functor_tag,
|
||||||
destroy_functor_tag
|
destroy_functor_tag,
|
||||||
|
check_functor_type_tag
|
||||||
};
|
};
|
||||||
|
|
||||||
// Tags used to decide between different types of functions
|
// Tags used to decide between different types of functions
|
||||||
@ -172,14 +187,27 @@ namespace boost {
|
|||||||
|
|
||||||
// The trivial manager does nothing but return the same pointer (if we
|
// The trivial manager does nothing but return the same pointer (if we
|
||||||
// are cloning) or return the null pointer (if we are deleting).
|
// are cloning) or return the null pointer (if we are deleting).
|
||||||
inline any_pointer trivial_manager(any_pointer f,
|
template<typename F>
|
||||||
functor_manager_operation_type op)
|
inline any_pointer
|
||||||
{
|
trivial_manager(any_pointer f, functor_manager_operation_type op)
|
||||||
if (op == clone_functor_tag)
|
{
|
||||||
return f;
|
switch (op) {
|
||||||
else
|
case clone_functor_tag: return f;
|
||||||
|
|
||||||
|
case destroy_functor_tag:
|
||||||
|
return make_any_pointer(reinterpret_cast<void*>(0));
|
||||||
|
|
||||||
|
case check_functor_type_tag:
|
||||||
|
{
|
||||||
|
std::type_info* t = static_cast<std::type_info*>(f.obj_ptr);
|
||||||
|
bool equal = BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(F), *t);
|
||||||
|
return equal? f : make_any_pointer(reinterpret_cast<void*>(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clears up a warning with GCC 3.2.3
|
||||||
return make_any_pointer(reinterpret_cast<void*>(0));
|
return make_any_pointer(reinterpret_cast<void*>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The functor_manager class contains a static function "manage" which
|
* The functor_manager class contains a static function "manage" which
|
||||||
@ -264,13 +292,59 @@ namespace boost {
|
|||||||
static any_pointer
|
static any_pointer
|
||||||
manage(any_pointer functor_ptr, functor_manager_operation_type op)
|
manage(any_pointer functor_ptr, functor_manager_operation_type op)
|
||||||
{
|
{
|
||||||
typedef typename get_function_tag<functor_type>::type tag_type;
|
if (op == check_functor_type_tag) {
|
||||||
return manager(functor_ptr, op, tag_type());
|
std::type_info* type =
|
||||||
|
static_cast<std::type_info*>(functor_ptr.obj_ptr);
|
||||||
|
bool equal =
|
||||||
|
BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(Functor), *type);
|
||||||
|
return (equal? functor_ptr
|
||||||
|
: make_any_pointer(reinterpret_cast<void*>(0)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
typedef typename get_function_tag<functor_type>::type tag_type;
|
||||||
|
return manager(functor_ptr, op, tag_type());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// A type that is only used for comparisons against zero
|
// A type that is only used for comparisons against zero
|
||||||
struct useless_clear_type {};
|
struct useless_clear_type {};
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_SFINAE
|
||||||
|
// These routines perform comparisons between a Boost.Function
|
||||||
|
// object and an arbitrary function object (when the last
|
||||||
|
// parameter is mpl::bool_<false>) or against zero (when the
|
||||||
|
// last parameter is mpl::bool_<true>). They are only necessary
|
||||||
|
// for compilers that don't support SFINAE.
|
||||||
|
template<typename Function, typename Functor>
|
||||||
|
bool
|
||||||
|
compare_equal(const Function& f, const Functor&, mpl::bool_<true>)
|
||||||
|
{ return f.empty(); }
|
||||||
|
|
||||||
|
template<typename Function, typename Functor>
|
||||||
|
bool
|
||||||
|
compare_not_equal(const Function& f, const Functor&, mpl::bool_<true>)
|
||||||
|
{ return !f.empty(); }
|
||||||
|
|
||||||
|
template<typename Function, typename Functor>
|
||||||
|
bool
|
||||||
|
compare_equal(const Function& f, const Functor& g, mpl::bool_<false>)
|
||||||
|
{
|
||||||
|
if (const Functor* fp = f.template contains<Functor>())
|
||||||
|
return *fp == g;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Function, typename Functor>
|
||||||
|
bool
|
||||||
|
compare_not_equal(const Function& f, const Functor& g,
|
||||||
|
mpl::bool_<false>)
|
||||||
|
{
|
||||||
|
if (const Functor* fp = f.template contains<Functor>())
|
||||||
|
return *fp != g;
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
#endif // BOOST_NO_SFINAE
|
||||||
} // end namespace function
|
} // end namespace function
|
||||||
} // end namespace detail
|
} // end namespace detail
|
||||||
|
|
||||||
@ -291,11 +365,59 @@ public:
|
|||||||
// Is this function empty?
|
// Is this function empty?
|
||||||
bool empty() const { return !manager; }
|
bool empty() const { return !manager; }
|
||||||
|
|
||||||
|
template<typename Functor>
|
||||||
|
Functor* contains()
|
||||||
|
{
|
||||||
|
if (!manager) return 0;
|
||||||
|
|
||||||
|
detail::function::any_pointer result =
|
||||||
|
manager(detail::function::make_any_pointer(&typeid(Functor)),
|
||||||
|
detail::function::check_functor_type_tag);
|
||||||
|
if (!result.obj_ptr) return false;
|
||||||
|
else {
|
||||||
|
typedef typename detail::function::get_function_tag<Functor>::type tag;
|
||||||
|
return get_functor_pointer<Functor>(tag(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Functor>
|
||||||
|
const Functor* contains() const
|
||||||
|
{
|
||||||
|
if (!manager) return 0;
|
||||||
|
|
||||||
|
detail::function::any_pointer result =
|
||||||
|
manager(detail::function::make_any_pointer(&typeid(Functor)),
|
||||||
|
detail::function::check_functor_type_tag);
|
||||||
|
if (!result.obj_ptr) return false;
|
||||||
|
else {
|
||||||
|
typedef typename detail::function::get_function_tag<Functor>::type tag;
|
||||||
|
return get_functor_pointer<Functor>(tag(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public: // should be protected, but GCC 2.95.3 will fail to allow access
|
public: // should be protected, but GCC 2.95.3 will fail to allow access
|
||||||
detail::function::any_pointer (*manager)(
|
detail::function::any_pointer (*manager)(
|
||||||
detail::function::any_pointer,
|
detail::function::any_pointer,
|
||||||
detail::function::functor_manager_operation_type);
|
detail::function::functor_manager_operation_type);
|
||||||
detail::function::any_pointer functor;
|
detail::function::any_pointer functor;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename Functor>
|
||||||
|
Functor* get_functor_pointer(detail::function::function_ptr_tag, int)
|
||||||
|
{ return &reinterpret_cast<Functor>(functor.func_ptr); }
|
||||||
|
|
||||||
|
template<typename Functor, typename Tag>
|
||||||
|
Functor* get_functor_pointer(Tag, long)
|
||||||
|
{ return static_cast<Functor*>(functor.obj_ptr); }
|
||||||
|
|
||||||
|
template<typename Functor>
|
||||||
|
const Functor*
|
||||||
|
get_functor_pointer(detail::function::function_ptr_tag, int) const
|
||||||
|
{ return &reinterpret_cast<const Functor>(functor.func_ptr); }
|
||||||
|
|
||||||
|
template<typename Functor, typename Tag>
|
||||||
|
const Functor* get_functor_pointer(Tag, long) const
|
||||||
|
{ return static_cast<const Functor*>(functor.const_obj_ptr); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -308,16 +430,7 @@ public:
|
|||||||
bad_function_call() : std::runtime_error("call to empty boost::function") {}
|
bad_function_call() : std::runtime_error("call to empty boost::function") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Poison comparison between Boost.Function objects (because it is
|
#ifndef BOOST_NO_SFINAE
|
||||||
* meaningless). The comparisons would otherwise be allowed because of the
|
|
||||||
* conversion required to allow syntax such as:
|
|
||||||
* boost::function<int, int> f;
|
|
||||||
* if (f) { f(5); }
|
|
||||||
*/
|
|
||||||
void operator==(const function_base&, const function_base&);
|
|
||||||
void operator!=(const function_base&, const function_base&);
|
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
|
|
||||||
inline bool operator==(const function_base& f,
|
inline bool operator==(const function_base& f,
|
||||||
detail::function::useless_clear_type*)
|
detail::function::useless_clear_type*)
|
||||||
{
|
{
|
||||||
|
@ -508,7 +508,7 @@ namespace boost {
|
|||||||
invoker_type;
|
invoker_type;
|
||||||
|
|
||||||
invoker = &invoker_type::invoke;
|
invoker = &invoker_type::invoke;
|
||||||
this->manager = &detail::function::trivial_manager;
|
this->manager = &detail::function::trivial_manager<FunctionObj>;
|
||||||
this->functor =
|
this->functor =
|
||||||
this->manager(
|
this->manager(
|
||||||
detail::function::make_any_pointer(
|
detail::function::make_any_pointer(
|
||||||
@ -529,7 +529,7 @@ namespace boost {
|
|||||||
>::type
|
>::type
|
||||||
invoker_type;
|
invoker_type;
|
||||||
invoker = &invoker_type::invoke;
|
invoker = &invoker_type::invoke;
|
||||||
this->manager = &detail::function::trivial_manager;
|
this->manager = &detail::function::trivial_manager<FunctionObj>;
|
||||||
this->functor = detail::function::make_any_pointer(this);
|
this->functor = detail::function::make_any_pointer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,6 +556,143 @@ namespace boost {
|
|||||||
f1.swap(f2);
|
f1.swap(f2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Poison comparisons between boost::function objects of the same type.
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator>
|
||||||
|
void operator==(const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>&,
|
||||||
|
const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>&);
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator>
|
||||||
|
void operator!=(const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>&,
|
||||||
|
const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>&);
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_SFINAE
|
||||||
|
// Comparisons between boost::function objects and arbitrary function objects
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator, typename Functor>
|
||||||
|
inline bool
|
||||||
|
operator==(const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>& f,
|
||||||
|
Functor g)
|
||||||
|
{
|
||||||
|
typedef mpl::bool_<(is_integral<Functor>::value)> integral;
|
||||||
|
return detail::function::compare_equal(f, g, integral());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator, typename Functor>
|
||||||
|
inline bool
|
||||||
|
operator==(Functor g,
|
||||||
|
const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>& f)
|
||||||
|
{
|
||||||
|
typedef mpl::bool_<(is_integral<Functor>::value)> integral;
|
||||||
|
return detail::function::compare_equal(f, g, integral());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator, typename Functor>
|
||||||
|
inline bool
|
||||||
|
operator!=(const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>& f,
|
||||||
|
Functor g)
|
||||||
|
{
|
||||||
|
typedef mpl::bool_<(is_integral<Functor>::value)> integral;
|
||||||
|
return detail::function::compare_not_equal(f, g, integral());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator, typename Functor>
|
||||||
|
inline bool
|
||||||
|
operator!=(Functor g,
|
||||||
|
const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>& f)
|
||||||
|
{
|
||||||
|
typedef mpl::bool_<(is_integral<Functor>::value)> integral;
|
||||||
|
return detail::function::compare_not_equal(f, g, integral());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
|
||||||
|
typename enable_if_c<(::boost::type_traits::ice_not< \
|
||||||
|
(is_integral<Functor>::value)>::value), \
|
||||||
|
Type>::type
|
||||||
|
|
||||||
|
// Comparisons between boost::function objects and arbitrary function objects
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator, typename Functor>
|
||||||
|
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
|
||||||
|
operator==(const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>& f,
|
||||||
|
Functor g)
|
||||||
|
{
|
||||||
|
if (const Functor* fp = f.template contains<Functor>()) return *fp == g;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator, typename Functor>
|
||||||
|
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
|
||||||
|
operator==(Functor g,
|
||||||
|
const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>& f)
|
||||||
|
{
|
||||||
|
if (const Functor* fp = f.template contains<Functor>()) return g == *fp;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator, typename Functor>
|
||||||
|
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
|
||||||
|
operator!=(const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>& f,
|
||||||
|
Functor g)
|
||||||
|
{
|
||||||
|
if (const Functor* fp = f.template contains<Functor>()) return *fp != g;
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Allocator, typename Functor>
|
||||||
|
BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
|
||||||
|
operator!=(Functor g,
|
||||||
|
const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Allocator>& f)
|
||||||
|
{
|
||||||
|
if (const Functor* fp = f.template contains<Functor>()) return g != *fp;
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
|
||||||
|
#endif // Compiler supporting SFINAE
|
||||||
|
|
||||||
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
|
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
|
||||||
|
|
||||||
#if BOOST_FUNCTION_NUM_ARGS == 0
|
#if BOOST_FUNCTION_NUM_ARGS == 0
|
||||||
|
@ -60,6 +60,8 @@ DEPENDS all : test ;
|
|||||||
[ run libs/function/test/function_ref_cxx98.cpp : : : : ]
|
[ run libs/function/test/function_ref_cxx98.cpp : : : : ]
|
||||||
|
|
||||||
[ run libs/function/test/function_ref_portable.cpp : : : : ]
|
[ run libs/function/test/function_ref_portable.cpp : : : : ]
|
||||||
|
|
||||||
|
[ run libs/function/test/contains_test.cpp : : : : ]
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
96
test/contains_test.cpp
Normal file
96
test/contains_test.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Boost.Function library
|
||||||
|
|
||||||
|
// Copyright Doug Gregor 2004. 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)
|
||||||
|
|
||||||
|
#include <boost/test/minimal.hpp>
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
#include <boost/ref.hpp>
|
||||||
|
|
||||||
|
static int forty_two() { return 42; }
|
||||||
|
|
||||||
|
struct Seventeen
|
||||||
|
{
|
||||||
|
int operator()() const { return 17; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReturnInt
|
||||||
|
{
|
||||||
|
explicit ReturnInt(int value) : value(value) {}
|
||||||
|
|
||||||
|
int operator()() const { return value; }
|
||||||
|
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const ReturnInt& x, const ReturnInt& y)
|
||||||
|
{ return x.value == y.value; }
|
||||||
|
|
||||||
|
bool operator!=(const ReturnInt& x, const ReturnInt& y)
|
||||||
|
{ return x.value != y.value; }
|
||||||
|
|
||||||
|
static void contains_test()
|
||||||
|
{
|
||||||
|
boost::function0<int> f;
|
||||||
|
|
||||||
|
f = &forty_two;
|
||||||
|
BOOST_TEST(*f.contains<int (*)()>() == &forty_two);
|
||||||
|
BOOST_TEST(!f.contains<Seventeen>());
|
||||||
|
|
||||||
|
f = Seventeen();
|
||||||
|
BOOST_TEST(!f.contains<int (*)()>());
|
||||||
|
BOOST_TEST(f.contains<Seventeen>());
|
||||||
|
|
||||||
|
Seventeen this_seventeen;
|
||||||
|
f = boost::ref(this_seventeen);
|
||||||
|
BOOST_TEST(!f.contains<int (*)()>());
|
||||||
|
BOOST_TEST(f.contains<Seventeen>());
|
||||||
|
BOOST_TEST(f.contains<Seventeen>() == &this_seventeen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void equal_test()
|
||||||
|
{
|
||||||
|
boost::function0<int> f;
|
||||||
|
|
||||||
|
f = &forty_two;
|
||||||
|
BOOST_TEST(f == &forty_two);
|
||||||
|
BOOST_TEST(&forty_two == f);
|
||||||
|
BOOST_TEST(f != ReturnInt(17));
|
||||||
|
BOOST_TEST(ReturnInt(17) != f);
|
||||||
|
|
||||||
|
f = ReturnInt(17);
|
||||||
|
BOOST_TEST(f != &forty_two);
|
||||||
|
BOOST_TEST(&forty_two != f);
|
||||||
|
BOOST_TEST(f == ReturnInt(17));
|
||||||
|
BOOST_TEST(ReturnInt(17) == f);
|
||||||
|
BOOST_TEST(f != ReturnInt(16));
|
||||||
|
BOOST_TEST(ReturnInt(16) != f);
|
||||||
|
|
||||||
|
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
|
||||||
|
boost::function<int(void)> g;
|
||||||
|
|
||||||
|
g = &forty_two;
|
||||||
|
BOOST_TEST(g == &forty_two);
|
||||||
|
BOOST_TEST(&forty_two == g);
|
||||||
|
BOOST_TEST(g != ReturnInt(17));
|
||||||
|
BOOST_TEST(ReturnInt(17) != g);
|
||||||
|
|
||||||
|
g = ReturnInt(17);
|
||||||
|
BOOST_TEST(g != &forty_two);
|
||||||
|
BOOST_TEST(&forty_two != g);
|
||||||
|
BOOST_TEST(g == ReturnInt(17));
|
||||||
|
BOOST_TEST(ReturnInt(17) == g);
|
||||||
|
BOOST_TEST(g != ReturnInt(16));
|
||||||
|
BOOST_TEST(ReturnInt(16) != g);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_main(int, char*[])
|
||||||
|
{
|
||||||
|
contains_test();
|
||||||
|
equal_test();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue
Block a user