- Added sig member template support for Boost.Lambda, with testcase (Michael Hohmuth)

- Removed the assignment-to-zero attempt

- Added bad_function_call exception (using boost::throw_exception)


[SVN r16102]
This commit is contained in:
Douglas Gregor
2002-11-04 18:19:01 +00:00
parent 9a09d9e044
commit 17ded4b8bf
6 changed files with 148 additions and 80 deletions

View File

@ -2,6 +2,7 @@
#define BOOST_FUNCTION_PROLOGUE_HPP
# include <cassert>
# include <algorithm>
# include <boost/throw_exception.hpp>
# include <boost/config.hpp>
# include <boost/function/function_base.hpp>
# include <boost/mem_fn.hpp>

View File

@ -17,6 +17,7 @@
#define BOOST_FUNCTION_BASE_HEADER
#include <stdexcept>
#include <string>
#include <memory>
#include <new>
#include <boost/config.hpp>
@ -255,52 +256,62 @@ namespace boost {
} // end namespace function
} // end namespace detail
/**
* The function_base class contains the basic elements needed for the
* function1, function2, function3, etc. classes. It is common to all
* functions (and as such can be used to tell if we have one of the
* functionN objects).
*/
class function_base
/**
* The function_base class contains the basic elements needed for the
* function1, function2, function3, etc. classes. It is common to all
* functions (and as such can be used to tell if we have one of the
* functionN objects).
*/
class function_base
{
public:
function_base() : manager(0)
{
public:
function_base() : manager(0)
functor.obj_ptr = 0;
}
// Is this function empty?
bool empty() const { return !manager; }
public: // should be protected, but GCC 2.95.3 will fail to allow access
detail::function::any_pointer (*manager)(
detail::function::any_pointer,
detail::function::functor_manager_operation_type);
detail::function::any_pointer functor;
};
/**
* The bad_function_call exception class is thrown when a boost::function
* object is invoked
*/
class bad_function_call : public std::runtime_error
{
public:
bad_function_call() : std::runtime_error("call to empty boost::function") {}
};
/* Poison comparison between Boost.Function objects (because it is
* 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&);
namespace detail {
namespace function {
inline bool has_empty_target(const function_base* f)
{
functor.obj_ptr = 0;
return f->empty();
}
// Is this function empty?
bool empty() const { return !manager; }
public: // should be protected, but GCC 2.95.3 will fail to allow access
detail::function::any_pointer (*manager)(
detail::function::any_pointer,
detail::function::functor_manager_operation_type);
detail::function::any_pointer functor;
};
/* Poison comparison between Boost.Function objects (because it is
* 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&);
namespace detail {
namespace function {
inline bool has_empty_target(const function_base* f)
{
return f->empty();
}
inline bool has_empty_target(...)
{
return false;
}
} // end namespace function
} // end namespace detail
}
inline bool has_empty_target(...)
{
return false;
}
} // end namespace function
} // end namespace detail
} // end namespace boost
#endif // BOOST_FUNCTION_BASE_HEADER

View File

@ -21,7 +21,6 @@
#define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
#define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
#define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
@ -247,6 +246,13 @@ namespace boost {
public:
BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
// add signature for boost::lambda
template<typename Args>
struct sig
{
typedef internal_result_type type;
};
#if BOOST_FUNCTION_NUM_ARGS == 1
typedef T0 argument_type;
#elif BOOST_FUNCTION_NUM_ARGS == 2
@ -289,7 +295,8 @@ namespace boost {
result_type operator()(BOOST_FUNCTION_PARMS) const
{
assert(!this->empty());
if (this->empty())
boost::throw_exception(bad_function_call());
internal_result_type result = invoker(function_base::functor
BOOST_FUNCTION_COMMA
@ -533,11 +540,6 @@ class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
BOOST_FUNCTION_COMMA Allocator> base_type;
typedef function self_type;
struct clear_type {};
class holder;
friend class holder;
public:
typedef typename base_type::allocator_type allocator_type;
@ -548,44 +550,28 @@ public:
function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
self_type& operator=(self_type& f)
function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
self_type& operator=(const self_type& f)
{
self_type(f).swap(*this);
return *this;
}
inline self_type& operator=(holder h);
self_type& operator=(clear_type*)
template<typename Functor>
self_type& operator=(Functor f)
{
this->clear();
self_type(f).swap(*this);
return *this;
}
self_type& operator=(const base_type& f)
{
self_type(f).swap(*this);
return *this;
}
};
template<typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>::holder
{
public:
template<typename F> holder(F f) : func(f) {}
holder(const base_type& f) : func(f) {}
holder(const self_type& f) : func(f) {}
self_type func;
};
template<typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>&
function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>::operator=(holder h)
{
h.func.swap(*this);
return *this;
}
#undef BOOST_FUNCTION_PARTIAL_SPEC
#endif // have partial specialization