forked from boostorg/function
Added support for target_type() member function (returns an std::type_info of
the underlying function object) and casting to retrieve the underyling target. [SVN r11360]
This commit is contained in:
@ -19,6 +19,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <new>
|
||||||
|
#include <typeinfo>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/type_traits.hpp>
|
#include <boost/type_traits.hpp>
|
||||||
|
|
||||||
@ -78,9 +80,11 @@ namespace boost {
|
|||||||
union any_pointer
|
union any_pointer
|
||||||
{
|
{
|
||||||
void* obj_ptr;
|
void* obj_ptr;
|
||||||
|
const void* const_obj_ptr;
|
||||||
void (*func_ptr)();
|
void (*func_ptr)();
|
||||||
|
|
||||||
explicit any_pointer(void* p) : obj_ptr(p) {}
|
explicit any_pointer(void* p) : obj_ptr(p) {}
|
||||||
|
explicit any_pointer(const void* p) : const_obj_ptr(p) {}
|
||||||
explicit any_pointer(void (*p)()) : func_ptr(p) {}
|
explicit any_pointer(void (*p)()) : func_ptr(p) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -109,7 +113,11 @@ 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 { clone_functor, destroy_functor };
|
enum functor_manager_operation_type {
|
||||||
|
clone_functor,
|
||||||
|
destroy_functor,
|
||||||
|
retrieve_type_info
|
||||||
|
};
|
||||||
|
|
||||||
// Tags used to decide between function and function object pointers.
|
// Tags used to decide between function and function object pointers.
|
||||||
struct function_ptr_tag {};
|
struct function_ptr_tag {};
|
||||||
@ -140,8 +148,10 @@ namespace boost {
|
|||||||
{
|
{
|
||||||
if (op == clone_functor)
|
if (op == clone_functor)
|
||||||
return function_ptr;
|
return function_ptr;
|
||||||
else
|
else if (op == destroy_functor)
|
||||||
return any_pointer(static_cast<void (*)()>(0));
|
return any_pointer(static_cast<void (*)()>(0));
|
||||||
|
else
|
||||||
|
return any_pointer(&typeid(Functor));
|
||||||
}
|
}
|
||||||
|
|
||||||
// For function object pointers, we clone the pointer to each
|
// For function object pointers, we clone the pointer to each
|
||||||
@ -171,7 +181,7 @@ namespace boost {
|
|||||||
# endif // BOOST_NO_STD_ALLOCATOR
|
# endif // BOOST_NO_STD_ALLOCATOR
|
||||||
return any_pointer(static_cast<void*>(new_f));
|
return any_pointer(static_cast<void*>(new_f));
|
||||||
}
|
}
|
||||||
else {
|
else if (op == destroy_functor) {
|
||||||
/* Cast from the void pointer to the functor pointer type */
|
/* Cast from the void pointer to the functor pointer type */
|
||||||
functor_type* f =
|
functor_type* f =
|
||||||
reinterpret_cast<functor_type*>(function_obj_ptr.obj_ptr);
|
reinterpret_cast<functor_type*>(function_obj_ptr.obj_ptr);
|
||||||
@ -190,8 +200,10 @@ namespace boost {
|
|||||||
|
|
||||||
return any_pointer(static_cast<void*>(0));
|
return any_pointer(static_cast<void*>(0));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return any_pointer(&typeid(Functor));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Dispatch to an appropriate manager based on whether we have a
|
/* Dispatch to an appropriate manager based on whether we have a
|
||||||
function pointer or a function object pointer. */
|
function pointer or a function object pointer. */
|
||||||
|
@ -46,6 +46,8 @@ namespace boost {
|
|||||||
virtual R call(BOOST_FUNCTION_PARMS) const = 0;
|
virtual R call(BOOST_FUNCTION_PARMS) const = 0;
|
||||||
virtual BOOST_FUNCTION_INVOKER_BASE* clone() const = 0;
|
virtual BOOST_FUNCTION_INVOKER_BASE* clone() const = 0;
|
||||||
virtual void destroy(BOOST_FUNCTION_INVOKER_BASE*) = 0;
|
virtual void destroy(BOOST_FUNCTION_INVOKER_BASE*) = 0;
|
||||||
|
virtual const std::type_info& type() const = 0;
|
||||||
|
virtual any_pointer pointer() const = 0;
|
||||||
};
|
};
|
||||||
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
||||||
|
|
||||||
@ -113,8 +115,18 @@ namespace boost {
|
|||||||
# endif // BOOST_NO_STD_ALLOCATOR
|
# endif // BOOST_NO_STD_ALLOCATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const std::type_info& type() const
|
||||||
|
{
|
||||||
|
return typeid(FunctionPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual any_pointer pointer() const
|
||||||
|
{
|
||||||
|
return any_pointer(reinterpret_cast<void (*)()>(function_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FunctionPtr function_ptr;
|
mutable FunctionPtr function_ptr;
|
||||||
#else
|
#else
|
||||||
static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
|
static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
|
||||||
BOOST_FUNCTION_PARMS)
|
BOOST_FUNCTION_PARMS)
|
||||||
@ -190,8 +202,18 @@ namespace boost {
|
|||||||
# endif // BOOST_NO_STD_ALLOCATOR
|
# endif // BOOST_NO_STD_ALLOCATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const std::type_info& type() const
|
||||||
|
{
|
||||||
|
return typeid(FunctionPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual any_pointer pointer() const
|
||||||
|
{
|
||||||
|
return any_pointer(reinterpret_cast<void (*)()>(function_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FunctionPtr function_ptr;
|
mutable FunctionPtr function_ptr;
|
||||||
# else
|
# else
|
||||||
static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
|
static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
|
||||||
BOOST_FUNCTION_PARMS)
|
BOOST_FUNCTION_PARMS)
|
||||||
@ -268,6 +290,16 @@ namespace boost {
|
|||||||
#endif // BOOST_NO_STD_ALLOCATOR
|
#endif // BOOST_NO_STD_ALLOCATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const std::type_info& type() const
|
||||||
|
{
|
||||||
|
return typeid(FunctionObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual any_pointer pointer() const
|
||||||
|
{
|
||||||
|
return any_pointer(&function_obj);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable FunctionObj function_obj;
|
mutable FunctionObj function_obj;
|
||||||
#else
|
#else
|
||||||
@ -346,6 +378,16 @@ namespace boost {
|
|||||||
# endif // BOOST_NO_STD_ALLOCATOR
|
# endif // BOOST_NO_STD_ALLOCATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const std::type_info& type() const
|
||||||
|
{
|
||||||
|
return typeid(FunctionObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual any_pointer pointer() const
|
||||||
|
{
|
||||||
|
return any_pointer(&function_obj);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable FunctionObj function_obj;
|
mutable FunctionObj function_obj;
|
||||||
# else
|
# else
|
||||||
@ -601,7 +643,73 @@ namespace boost {
|
|||||||
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::type_info& target_type() const
|
||||||
|
{
|
||||||
|
if (this->empty())
|
||||||
|
return typeid(void);
|
||||||
|
else {
|
||||||
|
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
||||||
|
impl_type* i = reinterpret_cast<impl_type*>(impl);
|
||||||
|
return i->type();
|
||||||
|
#else
|
||||||
|
detail::function::any_pointer p =
|
||||||
|
manager(functor, detail::function::retrieve_type_info);
|
||||||
|
return *static_cast<const std::type_info*>(p.const_obj_ptr);
|
||||||
|
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename To>
|
||||||
|
To& cast(To* = 0)
|
||||||
|
{
|
||||||
|
assert(typeid(To) != typeid(void));
|
||||||
|
assert(typeid(To) == this->target_type());
|
||||||
|
typedef typename detail::function::IF<(is_pointer<To>::value),
|
||||||
|
detail::function::function_ptr_tag,
|
||||||
|
detail::function::function_obj_tag>::type tag;
|
||||||
|
|
||||||
|
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
||||||
|
impl_type* i = reinterpret_cast<impl_type*>(impl);
|
||||||
|
return cast_helper<To>(i->pointer(), tag());
|
||||||
|
#else
|
||||||
|
return cast_helper<To>(functor, tag());
|
||||||
|
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename To>
|
||||||
|
const To& cast(To* = 0) const
|
||||||
|
{
|
||||||
|
assert(typeid(To) != typeid(void));
|
||||||
|
assert(typeid(To) == this->target_type());
|
||||||
|
typedef typename detail::function::IF<(is_pointer<To>::value),
|
||||||
|
detail::function::function_ptr_tag,
|
||||||
|
detail::function::function_obj_tag>::type tag;
|
||||||
|
|
||||||
|
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
||||||
|
impl_type* i = reinterpret_cast<impl_type*>(impl);
|
||||||
|
return cast_helper<To>(i->pointer(), tag());
|
||||||
|
#else
|
||||||
|
return cast_helper<To>(functor, tag());
|
||||||
|
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template<typename To>
|
||||||
|
To& cast_helper(detail::function::any_pointer p,
|
||||||
|
detail::function::function_ptr_tag,
|
||||||
|
To* = 0) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<To>(p.func_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename To>
|
||||||
|
To& cast_helper(detail::function::any_pointer p,
|
||||||
|
detail::function::function_obj_tag,
|
||||||
|
To* = 0) const
|
||||||
|
{
|
||||||
|
return *static_cast<To*>(p.obj_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
|
void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
|
||||||
{
|
{
|
||||||
if (!f.empty()) {
|
if (!f.empty()) {
|
||||||
@ -731,6 +839,36 @@ namespace boost {
|
|||||||
{
|
{
|
||||||
f1.swap(f2);
|
f1.swap(f2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename To, typename R
|
||||||
|
BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Policy, typename Mixin, typename Allocator>
|
||||||
|
inline To& function_cast(BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Policy,
|
||||||
|
Mixin,
|
||||||
|
Allocator
|
||||||
|
>& f,
|
||||||
|
To* = 0)
|
||||||
|
{
|
||||||
|
return f.template cast<To>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename To, typename R
|
||||||
|
BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
|
typename Policy, typename Mixin, typename Allocator>
|
||||||
|
inline const To& function_cast(const BOOST_FUNCTION_FUNCTION<
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS ,
|
||||||
|
Policy,
|
||||||
|
Mixin,
|
||||||
|
Allocator
|
||||||
|
>& f,
|
||||||
|
To* = 0)
|
||||||
|
{
|
||||||
|
return f.template cast<To>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup after ourselves...
|
// Cleanup after ourselves...
|
||||||
|
Reference in New Issue
Block a user