Compare commits

..

3 Commits

Author SHA1 Message Date
Douglas Gregor
c7b0bf3271 bad_error_eg.cpp:
- Example of error messages with and without compiler help


[SVN r13251]
2002-03-23 19:46:54 +00:00
Douglas Gregor
d793e792a5 errors.hpp:
- Check use of Boost.Function and emit reasonable error messages

function.hpp:
function_template.hpp:
  - Updated to use compiler-supported error messages


[SVN r13250]
2002-03-23 19:46:25 +00:00
nobody
970f1969a7 This commit was manufactured by cvs2svn to create branch
'compiler_supported_error_messages'.

[SVN r13249]
2002-03-22 12:16:42 +00:00
6 changed files with 521 additions and 105 deletions

View File

@@ -96,7 +96,7 @@ object. This is often referred to as "argument binding", and is beyond the scope
f(5); // Call x.foo(5)</pre></li>
<li><a href="../../lambda/doc/index.html">The Boost.Lambda library</a>. This library provides a powerful composition mechanism to construct function objects that uses very natural C++ syntax. Lambda requires a compiler that is reasonably conformant to the C++ standard. </li>
<li><a href="http://lambda.cs.utu.fi/">The Lambda library</a>. This library provides a powerful composition mechanism to construct function objects that uses very natural C++ syntax. Lambda requires a compiler that is reasonably conformant to the C++ standard. Note that it is not a Boost library.</li>
</ul>
<h3>References to Functions</h3>
@@ -199,7 +199,7 @@ boost::function2&lt;float, int, int, SynchronizedPolicy, SynchronizedMixin&gt; f
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 12:47:11 EDT 2001 -->
<!-- hhmts start -->
Last modified: Mon May 13 08:31:23 EDT 2002
Last modified: Fri Dec 14 19:58:14 EST 2001
<!-- hhmts end -->
</body>
</html>

View File

@@ -53,9 +53,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -78,9 +78,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -103,9 +103,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -128,9 +128,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -153,9 +153,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -178,9 +178,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -204,9 +204,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -230,9 +230,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -256,9 +256,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -282,9 +282,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -308,9 +308,9 @@ namespace boost {
typename T8,
typename T9,
typename T10,
typename Policy,
typename Mixin,
typename Allocator
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
struct params
{
@@ -454,16 +454,37 @@ namespace boost {
typedef function self_type;
function() : base_type() {}
#ifdef BOOST_COMPILER_HOOKS
template<typename Functor>
function(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) : base_type(f) {}
function(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) :
base_type(f, mixin_type(), detail::function::int_value<1>())
{
}
private:
template<typename Functor, int N>
function(Functor BOOST_FUNCTION_TARGET_FIX(const &) f,
detail::function::int_value<N>) :
base_type(f, mixin_type(), detail::function::int_value<N+1>())
{
}
public:
#else
template<typename Functor>
function(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) : base_type(f) {}
#endif // !BOOST_COMPILER_HOOKS
function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
template<typename Functor>
self_type& operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
#ifdef BOOST_COMPILER_HOOKS
self_type(f, detail::function::int_value<1>()).swap(*this);
#else
self_type(f).swap(*this);
#endif // !BOOST_COMPILER_HOOKS
return *this;
}

View File

@@ -0,0 +1,247 @@
// Boost.Function library
// Copyright (C) 2001 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.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
// Note: this header is a header template and must NOT have multiple-inclusion
// protection.
#ifdef BOOST_COMPILER_HOOKS
#ifndef BOOST_FUNCTION_ERRORS_HPP
# include <boost/config.hpp>
# include <boost/preprocessor/enum_params.hpp>
# include <boost/preprocessor/stringize.hpp>
# include <ext/compiler>
#endif // BOOST_FUNCTION_ERRORS_HPP
#define BOOST_F_BAD_ARGS \
BOOST_PP_CAT(incompatible_args_msg,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_F_CHECK_ARGS \
BOOST_PP_CAT(check_args,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_F_BAD_RETURN \
BOOST_PP_CAT(incompatible_return_msg,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_F_CHECK_RETURN \
BOOST_PP_CAT(check_return,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_F_CHECK_TARGET \
BOOST_PP_CAT(check_target,BOOST_FUNCTION_NUM_ARGS)
// Comma if nonzero number of arguments
#define BOOST_F_COMMA BOOST_PP_COMMA_IF(BOOST_FUNCTION_NUM_ARGS)
#define BOOST_F_TYPE_PLACEHOLDER(I,P) \
BOOST_PP_IF(I, ", ",) BOOST_PP_STRINGIZE(%t)
#define BOOST_F_ARG_TYPE(I,P) \
BOOST_PP_COMMA_IF(I) arg< type<T##I>
#define BOOST_F_CLOSE_TMPL(I, P) >
namespace boost {
namespace detail {
namespace function {
#ifndef BOOST_FUNCTION_ERRORS_HPP
template<bool> struct truth {};
template<int> struct int_value {};
using __gnu_cxx::arg;
using __gnu_cxx::type;
using __gnu_cxx::can_instantiate;
using __gnu_cxx::error;
template<typename T, void (T::*p)()>
struct pmf {};
template<typename Constraint>
struct constraint {
typedef pmf<Constraint, &Constraint::constraints> force;
};
template<bool, typename Error> struct maybe_emit_error;
template<typename Error> struct maybe_emit_error<true, Error> {};
template<typename Error>
struct maybe_emit_error<false, Error> {
BOOST_STATIC_CONSTANT(int, junk = sizeof(Error));
};
// Check the given constraint. If it is not satisfied, emit an error
// message suppressing N instantiation levels (not including the levels
// deeper than this instantiation).
template<typename Constraint, int N = 0>
struct check_constraint
{
// True if the constraint is met
BOOST_STATIC_CONSTANT(bool,
value = can_instantiate<constraint<Constraint> >
::value);
private:
// Possibly emit an error message
typedef typename Constraint::msg error_msg;
typedef typename error_msg::args error_msg_args;
typedef error<error_msg, error_msg_args, N+2> actual_error;
typedef maybe_emit_error<value, actual_error> possible_error;
BOOST_STATIC_CONSTANT(int, junk = sizeof(possible_error));
};
// Help suppress redundant error messages
template<bool, typename Check> struct maybe_check;
template<typename Check>
struct maybe_check<false, Check>
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<typename Check>
struct maybe_check<true, Check>
{
BOOST_STATIC_CONSTANT(bool, value = Check::value);
};
#endif // !BOOST_FUNCTION_ERRORS_HPP
// Error message when the arguments are not compatible
template<typename F BOOST_F_COMMA BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,typename T)>
struct BOOST_F_BAD_ARGS {
// Construct the argument list
typedef arg<type<F> BOOST_F_COMMA BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS, BOOST_F_ARG_TYPE, x) BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS, BOOST_F_CLOSE_TMPL, x) > args;
// The error message text
static const char* text;
};
#if BOOST_FUNCTION_NUM_ARGS == 0
template<typename F>
const char* BOOST_F_BAD_ARGS<F>::text
= "objects of type '%t' cannot be invoked with no arguments";
#else
// Construct the error message when arguments are not compatible
template<typename F BOOST_F_COMMA BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,typename T)>
const char* BOOST_F_BAD_ARGS<
F BOOST_F_COMMA
BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)>
::text = "objects of type '%t' cannot be invoked with Boost.Function "
"argument types '("
BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,
BOOST_F_TYPE_PLACEHOLDER,x)
")'";
#endif // BOOST_FUNCTION_NUM_ARGS != 0
// Concept check to determine if argument types are compatible
template<typename F BOOST_F_COMMA
BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,typename T)>
struct BOOST_F_CHECK_ARGS {
typedef BOOST_F_BAD_ARGS<F BOOST_F_COMMA BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)> msg;
F f;
#define BOOST_F_ARG(I,P) T##I a##I;
BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_F_ARG,)
#undef BOOST_F_ARG
void constraints()
{
f(BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,a));
}
};
// Error message when the return types are compatible
template<typename F, typename R BOOST_F_COMMA
BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,typename T)>
struct BOOST_F_BAD_RETURN {
// Arguments to format the error message
typedef arg<type<F> BOOST_F_COMMA BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS, BOOST_F_ARG_TYPE, x) , arg<type<R> > BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS, BOOST_F_CLOSE_TMPL, x) > args;
// Error message text
static const char* text;
};
#if BOOST_FUNCTION_NUM_ARGS == 0
template<typename F, typename R>
const char* BOOST_F_BAD_RETURN<F, R>::text =
"return type when invoking object of type '%t' with no arguments is "
"not convertible to Boost.Function declared return type '%t'";
#else
// Construct the error message when return types are not compatible
template<typename F, typename R BOOST_F_COMMA
BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,typename T)>
const char* BOOST_F_BAD_RETURN<
F, R BOOST_F_COMMA
BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)>
::text = "return type when invoking object of type '%t' with argument"
" types '("
BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,
BOOST_F_TYPE_PLACEHOLDER,x)
")' is not convertible to Boost.Function declared return "
"type '%t'";
#endif // BOOST_FUNCTION_NUM_ARGS != 0
// Concept check to determine if return types are compatible
template<typename F, typename R BOOST_F_COMMA
BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,typename T)>
struct BOOST_F_CHECK_RETURN {
typedef BOOST_F_BAD_RETURN<
F, R BOOST_F_COMMA
BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)> msg;
F f;
#define BOOST_F_ARG(I,P) T##I a##I;
BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_F_ARG,)
#undef BOOST_F_ARG
R foo()
{
return f(BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,a));
}
void constraints()
{
R (BOOST_F_CHECK_RETURN::*p)() = &BOOST_F_CHECK_RETURN::foo;
}
};
template<typename F, typename R BOOST_F_COMMA
BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,typename T),
int N=0>
struct BOOST_F_CHECK_TARGET {
typedef check_constraint<BOOST_F_CHECK_ARGS<F BOOST_F_COMMA BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)>,N+1> check_args;
typedef check_constraint<BOOST_F_CHECK_RETURN<F, R BOOST_F_COMMA BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)>,N+2> check_return;
BOOST_STATIC_CONSTANT(bool, args_ok = check_args::value);
BOOST_STATIC_CONSTANT(bool,
value =
(maybe_check<args_ok, check_return>::value));
};
} // end namespace function
} // end namespace function
} // end namespace function
#undef BOOST_F_COMMA
#undef BOOST_F_BAD_ARGS
#undef BOOST_F_CHECK_ARGS
#undef BOOST_F_BAD_RETURN
#undef BOOST_F_CHECK_RETURN
#undef BOOST_F_CHECK_TARGET
#undef BOOST_F_TYPE_PLACEHOLDER
#undef BOOST_F_ARG_TYPE
#undef BOOST_F_CLOSE_TMPL
#endif // BOOST_COMPILER_HOOKS
// Don't redo work done in the first inclusion
#ifndef BOOST_FUNCTION_ERRORS_HPP
# define BOOST_FUNCTION_ERRORS_HPP
#endif // BOOST_FUNCTION_ERRORS_HPP

View File

@@ -34,10 +34,8 @@
namespace boost {
namespace detail {
namespace function {
template<bool> struct truth {};
/*
* The ct_if implementation is temporary code. When a Boost metaprogramming
* The IF implementation is temporary code. When a Boost metaprogramming
* library is introduced, Boost.Function will use it instead.
*/
namespace intimate {
@@ -73,7 +71,7 @@ namespace boost {
} // end namespace intimate
template<bool Condition, typename Then, typename Else>
struct ct_if
struct IF
{
typedef typename intimate::Selector<Condition>::type select;
typedef typename select::template Result<Then,Else>::type type;
@@ -137,20 +135,20 @@ namespace boost {
template<typename F>
class get_function_tag
{
typedef typename ct_if<(is_pointer<F>::value),
typedef typename IF<(is_pointer<F>::value),
function_ptr_tag,
function_obj_tag>::type ptr_or_obj_tag;
typedef typename ct_if<(is_member_pointer<F>::value),
typedef typename IF<(is_member_pointer<F>::value),
member_ptr_tag,
ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
typedef typename ct_if<(is_reference_wrapper<F>::value),
typedef typename IF<(is_reference_wrapper<F>::value),
function_obj_ref_tag,
ptr_or_obj_or_mem_tag>::type or_ref_tag;
public:
typedef typename ct_if<(is_stateless<F>::value),
typedef typename IF<(is_stateless<F>::value),
stateless_function_obj_tag,
or_ref_tag>::type type;
};
@@ -158,7 +156,7 @@ namespace boost {
// The trivial manager does nothing but return the same pointer (if we
// are cloning) or return the null pointer (if we are deleting).
inline any_pointer trivial_manager(any_pointer f,
functor_manager_operation_type op)
functor_manager_operation_type op)
{
if (op == clone_functor_tag)
return f;
@@ -178,8 +176,7 @@ namespace boost {
// For function pointers, the manager is trivial
static inline any_pointer
manager(any_pointer function_ptr,
functor_manager_operation_type op,
manager(any_pointer function_ptr, functor_manager_operation_type op,
function_ptr_tag)
{
if (op == clone_functor_tag)
@@ -310,10 +307,6 @@ namespace boost {
detail::function::functor_manager_operation_type);
detail::function::any_pointer functor;
#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
// Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
operator bool () const { return !this->empty(); }
#else
private:
struct dummy {
void nonnull() {};
@@ -327,7 +320,6 @@ namespace boost {
safe_bool operator!() const
{ return (this->empty())? &dummy::nonnull : 0; }
#endif
};
/* Poison comparison between Boost.Function objects (because it is
@@ -341,14 +333,92 @@ namespace boost {
namespace detail {
namespace function {
inline bool has_empty_target(const function_base* f)
{
return f->empty();
/**
* Determine if the given target is empty.
*/
// Fallback - assume target is not empty
inline bool has_empty_target(...)
{
return false;
}
// If the target is a 'function', query the empty() method
inline bool has_empty_target(const function_base* af)
{
return af->empty();
}
inline bool has_empty_target(...)
// If the target is a 'function', query the empty() method
inline bool has_empty_target(const function_base& af)
{
return af.empty();
}
// A function pointer is empty if it is null
template<typename R>
inline bool has_empty_target(R (*f)())
{
return false;
return f == 0;
}
template<typename R, typename T1>
inline bool has_empty_target(R (*f)(T1))
{
return f == 0;
}
template<typename R, typename T1, typename T2>
inline bool has_empty_target(R (*f)(T1, T2))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3>
inline bool has_empty_target(R (*f)(T1, T2, T3))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7, T8))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9))
{
return f == 0;
}
} // end namespace function
} // end namespace detail
@@ -360,18 +430,14 @@ namespace boost {
inline void postcall(const function_base*) {}
};
// The default function mixin does nothing. The assignment and
// copy-construction operators are all defined because MSVC defines broken
// versions.
struct empty_function_mixin
{
empty_function_mixin() {}
empty_function_mixin(const empty_function_mixin&) {}
// The default function mixin does nothing. The assignment and copy-construction operators
// are all defined because MSVC defines broken versions.
struct empty_function_mixin {
empty_function_mixin() {};
empty_function_mixin(const empty_function_mixin&) {};
empty_function_mixin& operator=(const empty_function_mixin&)
{
return *this;
}
{return *this; }
};
}

View File

@@ -25,6 +25,9 @@
# include <boost/mem_fn.hpp>
#endif // BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP
// Include better error handling for
#include <boost/function/errors.hpp>
// Type of the default allocator
#ifndef BOOST_NO_STD_ALLOCATOR
# define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
@@ -41,6 +44,7 @@
// Class names used in this version of the code
#define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_BASE BOOST_JOIN(function_base,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_FUNCTION_INVOKER \
BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
@@ -167,7 +171,7 @@ namespace boost {
>
struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
{
typedef typename ct_if<(is_void<R>::value),
typedef typename IF<(is_void<R>::value),
BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
@@ -188,7 +192,7 @@ namespace boost {
>
struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
{
typedef typename ct_if<(is_void<R>::value),
typedef typename IF<(is_void<R>::value),
BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
@@ -209,7 +213,7 @@ namespace boost {
>
struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
{
typedef typename ct_if<(is_void<R>::value),
typedef typename IF<(is_void<R>::value),
BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
@@ -287,6 +291,16 @@ namespace boost {
this->assign_to_own(f);
}
#ifdef BOOST_COMPILER_HOOKS
template<typename Functor, int N>
BOOST_FUNCTION_FUNCTION(Functor f, const Mixin& m,
detail::function::int_value<N> iv) :
function_base(), Mixin(m), invoker(0)
{
this->assign_to(f, iv);
}
#endif // BOOST_COMPILER_HOOKS
~BOOST_FUNCTION_FUNCTION() { clear(); }
result_type operator()(BOOST_FUNCTION_PARMS) const
@@ -317,14 +331,25 @@ namespace boost {
BOOST_FUNCTION_FUNCTION&
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
#ifdef BOOST_COMPILER_HOOKS
self_type(f, static_cast<const Mixin&>(*this),
detail::function::int_value<1>()).swap(*this);
#else
self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
#endif // !BOOST_COMPILER_HOOKS
return *this;
}
template<typename Functor>
void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
#ifdef BOOST_COMPILER_HOOKS
self_type(f, static_cast<const Mixin&>(*this),
detail::function::int_value<1>()).swap(*this);
#else
self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
#endif // !BOOST_COMPILER_HOOKS
}
// Assignment from another BOOST_FUNCTION_FUNCTION
@@ -360,12 +385,9 @@ namespace boost {
// Clear out a target, if there is one
void clear()
{
if (function_base::manager) {
function_base::functor =
function_base::manager(function_base::functor,
detail::function::destroy_functor_tag);
}
if (function_base::manager)
function_base::functor = function_base::manager(function_base::functor, detail::function::destroy_functor_tag);
function_base::manager = 0;
invoker = 0;
}
@@ -376,17 +398,52 @@ namespace boost {
if (!f.empty()) {
invoker = f.invoker;
function_base::manager = f.manager;
function_base::functor =
f.manager(f.functor, detail::function::clone_functor_tag);
function_base::functor = f.manager(f.functor, detail::function::clone_functor_tag);
}
}
#ifdef BOOST_COMPILER_HOOKS
template<typename Functor>
void assign_to(Functor f)
{
return assign_to(f, detail::function::int_value<1>());
}
template<typename Functor, int N>
void assign_to(Functor f, detail::function::int_value<N>)
{
typedef detail::function::BOOST_JOIN(check_target,BOOST_FUNCTION_NUM_ARGS)<
Functor, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
N+2>
check_target;
enum { ok = check_target::value };
maybe_assign_to(f, detail::function::truth<ok>());
}
template<typename Functor>
void maybe_assign_to(Functor f, detail::function::truth<true>)
{
typedef typename detail::function::get_function_tag<Functor>::type tag;
this->assign_to(f, tag());
}
template<typename Functor>
void maybe_assign_to(Functor f, detail::function::truth<false>)
{
// Do nothing, to avoid even more error messages
}
#else
template<typename Functor>
void assign_to(Functor f)
{
typedef typename detail::function::get_function_tag<Functor>::type tag;
this->assign_to(f, tag());
}
#endif // !BOOST_COMPILER_HOOKS
template<typename FunctionPtr>
void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
@@ -402,10 +459,9 @@ namespace boost {
invoker_type;
invoker = &invoker_type::invoke;
function_base::manager =
&detail::function::functor_manager<FunctionPtr, Allocator>::manage;
function_base::functor =
function_base::manager(detail::function::any_pointer(
function_base::manager = &detail::function::functor_manager<FunctionPtr,
Allocator>::manage;
function_base::functor = function_base::manager(detail::function::any_pointer(
// should be a reinterpret cast, but some compilers
// insist on giving cv-qualifiers to free functions
(void (*)())(f)
@@ -425,7 +481,7 @@ namespace boost {
template<typename FunctionObj>
void assign_to(FunctionObj f, detail::function::function_obj_tag)
{
if (!detail::function::has_empty_target(addressof(f))) {
if (!detail::function::has_empty_target(&f)) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
@@ -435,23 +491,11 @@ namespace boost {
invoker_type;
invoker = &invoker_type::invoke;
function_base::manager = &detail::function::functor_manager<
FunctionObj, Allocator>::manage;
#ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<FunctionObj>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, f);
// Get back to the original pointer type
FunctionObj* new_f = static_cast<FunctionObj*>(copy);
#else
FunctionObj* new_f = new FunctionObj(f);
#endif // BOOST_NO_STD_ALLOCATOR
function_base::manager = &detail::function::functor_manager<FunctionObj,
Allocator>::manage;
function_base::functor =
detail::function::any_pointer(static_cast<void*>(new_f));
function_base::manager(detail::function::any_pointer(const_cast<FunctionObj*>(&f)),
detail::function::clone_functor_tag);
}
}
@@ -459,7 +503,7 @@ namespace boost {
void assign_to(const reference_wrapper<FunctionObj>& f,
detail::function::function_obj_ref_tag)
{
if (!detail::function::has_empty_target(f.get_pointer())) {
if (!detail::function::has_empty_target(&f.get())) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
@@ -471,10 +515,9 @@ namespace boost {
invoker = &invoker_type::invoke;
function_base::manager = &detail::function::trivial_manager;
function_base::functor =
function_base::manager(
detail::function::any_pointer(
const_cast<FunctionObj*>(f.get_pointer())),
detail::function::clone_functor_tag);
function_base::manager(detail::function::any_pointer(
const_cast<FunctionObj*>(&f.get())),
detail::function::clone_functor_tag);
}
}
@@ -526,6 +569,8 @@ namespace boost {
#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
#undef BOOST_FUNCTION_COMMA
#undef BOOST_FUNCTION_FUNCTION
#undef BOOST_FUNCTION_BASE
#undef BOOST_FUNCTION_INVOKER_BASE
#undef BOOST_FUNCTION_FUNCTION_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
@@ -536,3 +581,4 @@ namespace boost {
#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER

36
test/bad_error_eg.cpp Normal file
View File

@@ -0,0 +1,36 @@
// Boost.Function library
// Copyright (C) 2001 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.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/function.hpp>
using namespace boost;
class X {};
int foo(X*);
X* bar(double);
int test_main(int, char* [])
{
function<int, float> f(&foo);
f = &bar;
BOOST_CRITICAL_ERROR("This should not have compiled.");
return 0;
}