diff --git a/include/boost/function/detail/prologue.hpp b/include/boost/function/detail/prologue.hpp index fd51cc7..ad273ae 100644 --- a/include/boost/function/detail/prologue.hpp +++ b/include/boost/function/detail/prologue.hpp @@ -6,6 +6,7 @@ # include # include # include +# include # include # include # include diff --git a/include/boost/function/function_base.hpp b/include/boost/function/function_base.hpp index 52c07af..16fb900 100644 --- a/include/boost/function/function_base.hpp +++ b/include/boost/function/function_base.hpp @@ -27,13 +27,13 @@ #include #include -#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 #else # define BOOST_FUNCTION_TARGET_FIX(x) #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. // boost::python::objects::function has to be seen by the compiler before the // boost::function class template. @@ -42,6 +42,12 @@ namespace boost { namespace python { namespace objects { }}} #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) namespace boost { @@ -253,6 +259,30 @@ namespace boost { return manager(functor_ptr, op, tag_type()); } }; + + template + struct enabled + { + template + struct base + { + typedef T type; + }; + }; + + template<> + struct enabled + { + template + struct base + { + }; + }; + + template + struct enable_if : public enabled::template base + { + }; } // end namespace function } // end namespace detail diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index 79a8a82..202015b 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -243,6 +243,8 @@ namespace boost { typedef typename detail::function::function_return_type::type internal_result_type; + struct clear_type {}; + public: 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 // one with a default parameter. template - 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::value), + int>::type = 0 +#endif // BOOST_FUNCTION_NO_ENABLE_IF + ) : function_base(), invoker(0) { 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) : function_base(), invoker(0) @@ -315,13 +327,27 @@ namespace boost { // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to // construct. template +#ifndef BOOST_FUNCTION_NO_ENABLE_IF + typename detail::function::enable_if< + (!is_same::value), + BOOST_FUNCTION_FUNCTION&>::type +#else BOOST_FUNCTION_FUNCTION& +#endif operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) { self_type(f).swap(*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 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) { @@ -540,13 +566,28 @@ class function BOOST_FUNCTION_COMMA Allocator> base_type; typedef function self_type; + struct clear_type {}; + public: typedef typename base_type::allocator_type allocator_type; function() : base_type() {} template - 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::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(f)){} @@ -559,12 +600,27 @@ public: } template - self_type& operator=(Functor f) +#ifndef BOOST_FUNCTION_NO_ENABLE_IF + typename detail::function::enable_if< + (!is_same::value), + self_type&>::type +#else + self_type& +#endif + operator=(Functor f) { self_type(f).swap(*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(f).swap(*this); diff --git a/test/function_n_test.cpp b/test/function_n_test.cpp index 93bed46..19942f0 100644 --- a/test/function_n_test.cpp +++ b/test/function_n_test.cpp @@ -13,8 +13,7 @@ // For more information, see http://www.boost.org -#define BOOST_INCLUDE_MAIN -#include +#include #include #include #include @@ -97,8 +96,12 @@ test_zero_args() v1(); BOOST_TEST(global_int == 5); - // clear() + // clear +#ifndef BOOST_FUNCTION_NO_ENABLE_IF + v1 = 0; +#else v1.clear(); +#endif BOOST_TEST(v1.empty()); // Assignment to an empty function from a free function @@ -491,6 +494,19 @@ test_zero_args() v8(); 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 typedef function0 func_int_type; generate_five_obj gen_five; diff --git a/test/function_test.cpp b/test/function_test.cpp index 706e9cf..99c4e97 100644 --- a/test/function_test.cpp +++ b/test/function_test.cpp @@ -1,6 +1,6 @@ // 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 // provided this copyright notice appears in all copies. @@ -13,9 +13,7 @@ // For more information, see http://www.boost.org -#define BOOST_INCLUDE_MAIN -#define BOOST_FUNCTION_NO_DEPRECATED -#include +#include #include #include #include @@ -99,7 +97,11 @@ test_zero_args() BOOST_TEST(global_int == 5); // clear +#ifndef BOOST_FUNCTION_NO_ENABLE_IF + v1 = 0; +#else v1.clear(); +#endif BOOST_TEST(0 == v1); // Assignment to an empty function from a free function @@ -492,6 +494,15 @@ test_zero_args() v8(); 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 typedef function func_int_type; generate_five_obj gen_five;