Boost logo

Boost :

From: William Kempf (sirwillard_at_[hidden])
Date: 2000-11-17 10:44:44


--- In boost_at_[hidden], Jesse Jones <jejones_at_a...> wrote:
> >> Or, alternatively, you can assign a function with two arguments
to a
> >> callback with one if the second argument has a default value.
> >>
> >I don't know how you are going to do this, the default value
doesn't appear
> >to travel with the function. If you know how, please let me know.
>
> You have to treat the function as a black box (ie you can't expload
it and
> pick out the argument types). I've appended a stripped down version
of the
> code I use below. I think it supports all the requirements
mentioned so far
> except allowing a function that returns a value to be assigned to a
> callback that returns void. I had a nice meta-programming fix for
this, but
> I couldn't get it past CW 5.3 so in the real code I specialized
> FunctorCallback1 and MethodCallback1 for void RETURN_TYPE's.

Thanks to Jesse's post I've attached a working implementation for a
callback returning a templated value and taking no arguments. This
can be extrapolated for N arguments, but to keep the discussion
simple and because thread doesn't need them I've kept it to no
arguments. Also, as I stated in another reply taking care of the
void return "coercion" is "simple" to handle with template
specializations for void return types, but since I'm using VC++ I've
not included this feature since it would confuse the code.

This code could be the basis for further discussion on this topic, so
criticisms and comments are more than welcomed!

#ifndef BOOST_CALLBACK_HPP
#define BOOST_CALLBACK_HPP

#include "atomic.hpp"

namespace boost {

namespace detail {

template <typename R>
struct base_callback0_impl
{
        base_callback0_impl() : m_refs(1) { }
        virtual ~base_callback0_impl() { }
        virtual R call()=0;
        atomic_t m_refs;
};

template <typename F, typename R>
struct callback0_impl : public base_callback0_impl<R>
{
        callback0_impl(F func) : m_func(func) { }
        virtual ~callback0_impl() { }
        virtual R call() { return m_func(); }
        F m_func;
};

};

template <typename R>
class callback0
{
public:
        typedef R return_type;

        template <typename F>
        callback0(F func) : m_impl(new detail::callback0_impl<F, R>
(func)) {
        }
        callback0(const callback0<R>& other) : m_impl(other.m_impl) {
                increment(m_impl->m_refs);
        }
        ~callback0() {
                if (decrement(m_impl->m_refs) == 0)
                        delete m_impl;
        }
        const callback0<R>& operator=(const callback0<R>& other) {
                if (decrement(m_impl->m_refs) == 0)
                        delete m_impl;
                m_impl = other.m_impl;
                increment(m_impl->m_refs);
        }
        R operator()() { return m_impl->call(); }

private:
        detail::base_callback0_impl<R>* m_impl;
};

}; // namespace boost

#endif // BOOST_CALLBACK_HPP


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk