Support assignment from 0, construction from 0, and comparison to zero.

[SVN r16174]
This commit is contained in:
Douglas Gregor
2002-11-09 16:02:47 +00:00
parent 4fed545468
commit 17b311cbbd
5 changed files with 126 additions and 12 deletions

View File

@ -6,6 +6,7 @@
# include <boost/config.hpp> # include <boost/config.hpp>
# include <boost/function/function_base.hpp> # include <boost/function/function_base.hpp>
# include <boost/mem_fn.hpp> # include <boost/mem_fn.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/preprocessor/enum.hpp> # include <boost/preprocessor/enum.hpp>
# include <boost/preprocessor/enum_params.hpp> # include <boost/preprocessor/enum_params.hpp>
# include <boost/preprocessor/cat.hpp> # include <boost/preprocessor/cat.hpp>

View File

@ -27,13 +27,13 @@
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/pending/ct_if.hpp> #include <boost/pending/ct_if.hpp>
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_NO_CONFIG)
# define BOOST_FUNCTION_TARGET_FIX(x) x # define BOOST_FUNCTION_TARGET_FIX(x) x
#else #else
# define BOOST_FUNCTION_TARGET_FIX(x) # define BOOST_FUNCTION_TARGET_FIX(x)
#endif // not MSVC #endif // not MSVC
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_NO_CONFIG)
// Work around a compiler bug. // Work around a compiler bug.
// boost::python::objects::function has to be seen by the compiler before the // boost::python::objects::function has to be seen by the compiler before the
// boost::function class template. // boost::function class template.
@ -42,6 +42,12 @@ namespace boost { namespace python { namespace objects {
}}} }}}
#endif #endif
// GCC 3.2 doesn't seem to support enable_if, so we assume that
// earlier versions have the same limitation
#if defined(__GNUC__) && __GNUC__ < 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ <= 2 ) && !(BOOST_NO_CONFIG)
# define BOOST_FUNCTION_NO_ENABLE_IF
#endif
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace boost { namespace boost {
@ -253,6 +259,30 @@ namespace boost {
return manager(functor_ptr, op, tag_type()); return manager(functor_ptr, op, tag_type());
} }
}; };
template<bool>
struct enabled
{
template<typename T>
struct base
{
typedef T type;
};
};
template<>
struct enabled<false>
{
template<typename T>
struct base
{
};
};
template<bool Enabled, typename T>
struct enable_if : public enabled<Enabled>::template base<T>
{
};
} // end namespace function } // end namespace function
} // end namespace detail } // end namespace detail

View File

@ -243,6 +243,8 @@ namespace boost {
typedef typename detail::function::function_return_type<R>::type typedef typename detail::function::function_return_type<R>::type
internal_result_type; internal_result_type;
struct clear_type {};
public: public:
BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
@ -277,13 +279,23 @@ namespace boost {
// MSVC chokes if the following two constructors are collapsed into // MSVC chokes if the following two constructors are collapsed into
// one with a default parameter. // one with a default parameter.
template<typename Functor> template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) : BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
,typename detail::function::enable_if<
(!is_same<Functor, int>::value),
int>::type = 0
#endif // BOOST_FUNCTION_NO_ENABLE_IF
) :
function_base(), function_base(),
invoker(0) invoker(0)
{ {
this->assign_to(f); this->assign_to(f);
} }
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
BOOST_FUNCTION_FUNCTION(clear_type*) : function_base(), invoker(0) {}
#endif // BOOST_FUNCTION_NO_ENABLE_IF
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
function_base(), function_base(),
invoker(0) invoker(0)
@ -315,13 +327,27 @@ namespace boost {
// handle BOOST_FUNCTION_FUNCTION as the type of the temporary to // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
// construct. // construct.
template<typename Functor> template<typename Functor>
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
typename detail::function::enable_if<
(!is_same<Functor, int>::value),
BOOST_FUNCTION_FUNCTION&>::type
#else
BOOST_FUNCTION_FUNCTION& BOOST_FUNCTION_FUNCTION&
#endif
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{ {
self_type(f).swap(*this); self_type(f).swap(*this);
return *this; return *this;
} }
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
{
this->clear();
return *this;
}
#endif // BOOST_FUNCTION_NO_ENABLE_IF
// Assignment from another BOOST_FUNCTION_FUNCTION // Assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
{ {
@ -540,13 +566,28 @@ class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
BOOST_FUNCTION_COMMA Allocator> base_type; BOOST_FUNCTION_COMMA Allocator> base_type;
typedef function self_type; typedef function self_type;
struct clear_type {};
public: public:
typedef typename base_type::allocator_type allocator_type; typedef typename base_type::allocator_type allocator_type;
function() : base_type() {} function() : base_type() {}
template<typename Functor> template<typename Functor>
function(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) : base_type(f) {} function(Functor f
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
,typename detail::function::enable_if<
(!is_same<Functor, int>::value),
int>::type = 0
#endif
) :
base_type(f)
{
}
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
function(clear_type*) : base_type() {}
#endif
function(const self_type& f) : base_type(static_cast<const base_type&>(f)){} function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
@ -559,12 +600,27 @@ public:
} }
template<typename Functor> template<typename Functor>
self_type& operator=(Functor f) #ifndef BOOST_FUNCTION_NO_ENABLE_IF
typename detail::function::enable_if<
(!is_same<Functor, int>::value),
self_type&>::type
#else
self_type&
#endif
operator=(Functor f)
{ {
self_type(f).swap(*this); self_type(f).swap(*this);
return *this; return *this;
} }
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
self_type& operator=(clear_type*)
{
this->clear();
return *this;
}
#endif
self_type& operator=(const base_type& f) self_type& operator=(const base_type& f)
{ {
self_type(f).swap(*this); self_type(f).swap(*this);

View File

@ -13,8 +13,7 @@
// For more information, see http://www.boost.org // For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN #include <boost/test/minimal.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <functional> #include <functional>
#include <cassert> #include <cassert>
@ -97,8 +96,12 @@ test_zero_args()
v1(); v1();
BOOST_TEST(global_int == 5); BOOST_TEST(global_int == 5);
// clear() // clear
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
v1 = 0;
#else
v1.clear(); v1.clear();
#endif
BOOST_TEST(v1.empty()); BOOST_TEST(v1.empty());
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
@ -491,6 +494,19 @@ test_zero_args()
v8(); v8();
BOOST_TEST(global_int == 2); BOOST_TEST(global_int == 2);
// Test construction from 0 and comparison to 0
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
func_void_type v9(0);
#else
func_void_type v9; // just default construct
#endif
#if !defined(BOOST_MSVC)
BOOST_TEST(v9 == 0);
BOOST_TEST(0 == v9);
#else
BOOST_TEST(v9.empty());
#endif
// Test return values // Test return values
typedef function0<int> func_int_type; typedef function0<int> func_int_type;
generate_five_obj gen_five; generate_five_obj gen_five;

View File

@ -1,6 +1,6 @@
// Boost.Function library // Boost.Function library
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu) // Copyright (C) 2001, 2002 Doug Gregor (gregod@cs.rpi.edu)
// //
// Permission to copy, use, sell and distribute this software is granted // Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies. // provided this copyright notice appears in all copies.
@ -13,9 +13,7 @@
// For more information, see http://www.boost.org // For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN #include <boost/test/minimal.hpp>
#define BOOST_FUNCTION_NO_DEPRECATED
#include <boost/test/test_tools.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <functional> #include <functional>
#include <cassert> #include <cassert>
@ -99,7 +97,11 @@ test_zero_args()
BOOST_TEST(global_int == 5); BOOST_TEST(global_int == 5);
// clear // clear
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
v1 = 0;
#else
v1.clear(); v1.clear();
#endif
BOOST_TEST(0 == v1); BOOST_TEST(0 == v1);
// Assignment to an empty function from a free function // Assignment to an empty function from a free function
@ -492,6 +494,15 @@ test_zero_args()
v8(); v8();
BOOST_TEST(global_int == 2); BOOST_TEST(global_int == 2);
// Test construction from 0 and comparison to 0
#ifndef BOOST_FUNCTION_NO_ENABLE_IF
func_void_type v9(0);
#else
func_void_type v9; // just default construct
#endif
BOOST_TEST(v9 == 0);
BOOST_TEST(0 == v9);
// Test return values // Test return values
typedef function<int ()> func_int_type; typedef function<int ()> func_int_type;
generate_five_obj gen_five; generate_five_obj gen_five;