Boost logo

Boost :

From: John Maddock (John_Maddock_at_[hidden])
Date: 2000-05-16 06:36:50


Mark,

>They certainly did, thank you! I now have it all working with
both C++Builder 4 and g++, including the binders. I'll post an
updated version to the vault shortly.<

I let a little buglet creep into the code I posted:

template <class Predicate>
unary_negate<typename make_functor<Predicate>::type> not1(const Predicate&
pred)
{
  return unary_negate<typename make_functor<Predicate>::type>((typename
make_functor<Predicate>::type)pred);
}

The type-cast here was a C++ Builder specific workaround - C++ Builder
seems to treat references to functions and pointers to functions as the
same type, so "const F&" gets degraded to "const F*" which means it can't
be passed to the function objects constructor without a const_cast. The
problem is that if T is a function object, then the cast generates a
temporary copy of the object, one workaround is to add a "cast_type" member
to make_functor (this ain't pretty but it does work!), here is my revised
test case:

#include <typeinfo>
#include <iostream>
#include <functional>
#include <boost/call_traits.hpp>

namespace boost{

template <class Operation>
struct unary_traits
{
  typedef typename Operation::result_type result_type;
  typedef typename Operation::argument_type argument_type;
};

template <class R, class A>
struct unary_traits<R(*)(A)>
{
  typedef R result_type;
  typedef A argument_type;
};

template <class F>
struct make_functor_ind;

template <class T>
struct make_functor_ind<T*>
{
   typedef T type;
   typedef const T& cast_type;
};

template <class R, class A>
struct make_functor_ind<R (*)(A)>
{
   typedef R(*type)(A);
   typedef R(*cast_type)(A);
};

template <class F>
struct make_functor : public make_functor_ind<F*>{};

template <class R, class A>
struct make_functor<R (*)(A)>
{
   typedef R(*type)(A);
   typedef R(*cast_type)(A);
};

//
--------------------------------------------------------------------------
// unary_negate, not1
//
--------------------------------------------------------------------------
template <class Predicate>
class unary_negate
  : public std::unary_function<typename
unary_traits<Predicate>::argument_type,bool>
{
public:
  explicit unary_negate(const Predicate &x)
      :
      pred(x)
  {}
  bool operator()(typename call_traits<typename
unary_traits<Predicate>::argument_type>::param_type x) const
  {
      return !pred(x);
  }
private:
  Predicate pred;
};

template <class Predicate>
unary_negate<typename make_functor<Predicate>::type> not1(const Predicate&
pred)
{
  return unary_negate<typename make_functor<Predicate>::type>
      ((typename make_functor<Predicate>::cast_type)(pred));
}

} // boost

bool f1(int i)
{ return (i == 0); }

int main()
{
   if(boost::not1(f1)(0) != boost::not1(std::ptr_fun(f1))(0))
      exit(1);
   return 0;
}

- John.


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