Boost logo

Boost :

From: David Abrahams (abrahams_at_[hidden])
Date: 2000-09-06 08:25:47


Hi Boris,

Here is a patch that will let you use binders on functors with void return
values with MSVC. The problem with MSVC is twofold (only 2?;->):

1. It chokes on returning the result of a function which returns void.
2. No partial specialization, so it's hard to make binder1st different when
the return value is void.

Here's an application of my "poor man's partial specialization" technique
which gets around the problem. I'm cc:'ing the boost list because some
people there are interested in such things.

Regards,
Dave

---------

#ifndef __STL_MSVC
template <class _Operation>
class binder1st :
    public unary_function<typename
__BINARY_ARG(_Operation,second_argument_type),
                          typename __BINARY_ARG(_Operation,result_type) > {
protected:
  _Operation _M_op;
  typename _Operation::first_argument_type _M_value;
public:
  binder1st(const _Operation& __x,
            const typename _Operation::first_argument_type& __y)
      : _M_op(__x), _M_value(__y) {}
  typename _Operation::result_type
  operator()(const typename _Operation::second_argument_type& __x) const {
    return _M_op(_M_value, __x);
  }
};
#else // Use "Poor man's partial specialization" so we can handle void
return values
template <class _ResultType>
struct _Binder1stSelect
{
    template <class _Operation>
    class _Binder1st :
        public unary_function<typename
__BINARY_ARG(_Operation,second_argument_type),
        typename __BINARY_ARG(_Operation,result_type) >
    {
    protected:
        _Operation _M_op;
        typename _Operation::first_argument_type _M_value;
    public:
        _Binder1st(const _Operation& __x,
                  const typename _Operation::first_argument_type& __y)
            : _M_op(__x), _M_value(__y) {}
        typename _Operation::result_type
            operator()(const typename _Operation::second_argument_type& __x)
const {
            return _M_op(_M_value, __x);
        }
    };
};

template <>
struct _Binder1stSelect<void>
{
    template <class _Operation>
    class _Binder1st :
        public unary_function<typename
__BINARY_ARG(_Operation,second_argument_type),
        typename __BINARY_ARG(_Operation,result_type) >
    {
    protected:
        _Operation _M_op;
        typename _Operation::first_argument_type _M_value;
    public:
        _Binder1st(const _Operation& __x,
                  const typename _Operation::first_argument_type& __y)
            : _M_op(__x), _M_value(__y) {}
        typename _Operation::result_type
            operator()(const typename _Operation::second_argument_type& __x)
const {
            _M_op(_M_value, __x);
        }
    };
};

template <class _Operation>
struct binder1st : _Binder1stSelect<typename
__BINARY_ARG(_Operation,result_type)>::_Binder1st<_Operation>
{
    binder1st(const _Operation& __x,
              const typename _Operation::first_argument_type& __y)
        :
_Binder1stSelect<__BINARY_ARG(_Operation,result_type)>::_Binder1st<_Operatio
n>(__x, __y) {}
};
#endif

template <class _Operation, class _Tp>
inline binder1st<_Operation>
bind1st(const _Operation& __fn, const _Tp& __x)
{
  typedef typename _Operation::first_argument_type _Arg1_type;
  return binder1st<_Operation>(__fn, _Arg1_type(__x));
}

#ifndef __STL_MSVC
template <class _Operation>
class binder2nd
  : public unary_function<typename
__BINARY_ARG(_Operation,first_argument_type),
                          typename __BINARY_ARG(_Operation,result_type)> {
protected:
  _Operation _M_op;
  typename _Operation::second_argument_type value;
public:
  binder2nd(const _Operation& __x,
            const typename _Operation::second_argument_type& __y)
      : _M_op(__x), value(__y) {}
  typename _Operation::result_type
  operator()(const typename _Operation::first_argument_type& __x) const {
    return _M_op(__x, value);
  }
};
#else // Use "Poor man's partial specialization" so we can handle void
return values
template <class _ResultType>
struct _Binder2ndSelect
{
    template <class _Operation>
    class _Binder2nd
        : public unary_function<typename
__BINARY_ARG(_Operation,first_argument_type),
        typename __BINARY_ARG(_Operation,result_type)>
    {
    protected:
        _Operation _M_op;
        typename _Operation::second_argument_type value;
    public:
        _Binder2nd(const _Operation& __x,
                   const typename _Operation::second_argument_type& __y)
            : _M_op(__x), value(__y) {}
        typename _Operation::result_type
            operator()(const typename _Operation::first_argument_type& __x)
const {
            return _M_op(__x, value);
        }
    };
};
template <>
struct _Binder2ndSelect<void>
{
    template <class _Operation>
    class _Binder2nd
        : public unary_function<typename
__BINARY_ARG(_Operation,first_argument_type),
        typename __BINARY_ARG(_Operation,result_type)>
    {
    protected:
        _Operation _M_op;
        typename _Operation::second_argument_type value;
    public:
        _Binder2nd(const _Operation& __x,
                   const typename _Operation::second_argument_type& __y)
            : _M_op(__x), value(__y) {}
        typename _Operation::result_type
            operator()(const typename _Operation::first_argument_type& __x)
const {
            _M_op(__x, value);
        }
    };
};

template <class _Operation>
struct binder2nd : _Binder2ndSelect<typename
__BINARY_ARG(_Operation,result_type)>::_Binder2nd<_Operation>
{
    binder2nd(const _Operation& __x,
              const typename _Operation::second_argument_type& __y)
        :
_Binder2ndSelect<__BINARY_ARG(_Operation,result_type)>::_Binder2nd<_Operatio
n>(__x, __y) {}
};
#endif


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