Boost logo

Boost Users :

From: Christian Rössel (christian.roessel_at_[hidden])
Date: 2006-05-19 06:39:11


Christian Rössel wrote:
> Dear list,
>
> I have a class Manager that wraps an associative container (e.g. std::map)
> and that provides a method that calls a std::find_if to search on the
> mapped_type.
>
> template <typename Func>
> boost::optional<Value&> find_if (Func func);
>
> I want to pass free functions, functors, boost::function objects or
> boost::lambda expressions to it. There is no problem with free functions
> and functors but with boost::function objects (not always) and
> boost::lambda expressions. The two lines that do not compile are commented
> in the code below. Please find the entire error messages attached.
>
> What am I doing wrong?
>
> Thanks and best regards,
> Christian
>
>
> #include <boost/optional.hpp>
> #include <boost/utility.hpp>
> #include <boost/function.hpp>
> #include <boost/lambda/lambda.hpp>
> #include <boost/lambda/bind.hpp>
> #include <algorithm>
> #include <map>
> #include <utility>
>
> template <typename Key,
> typename Value,
> template <typename Key,
> typename Value,
> typename Compare,
> typename Alloc> class AssocContainer,
> typename Compare = std::less<Key>,
> typename Alloc = std::allocator<std::pair<const Key, Value> >
>
>>>
>
> class Manager
> : public boost::noncopyable
> {
>
> public:
> typedef AssocContainer<Key, Value, Compare, Alloc> AssocCont;
> typedef Value value_type;
>
> Manager (const Compare& compare = Compare (),
> const Alloc& alloc = Alloc ())
> : cont_ (compare, alloc)
> {}
>
> ~Manager ()
> {
> cont_.clear ();
> }
>
> bool insert (Key key, Value value)
> {
> return cont_.insert (std::make_pair(key, value)).second;
> }
>
> template <typename Func>
> boost::optional<Value&> find_if (Func func)
> {
> using boost::lambda::_1;
> using boost::lambda::bind;
>
> typename AssocCont::iterator findResult =
> std::find_if (cont_.begin (), cont_.end (),
> bind(func, bind(&AssocCont::value_type::second, _1)));
> if (findResult != cont_.end()) {
> return boost::optional<Value&> (findResult->second);
> }
> return boost::optional<Value&> ();
> }
>
> private:
> AssocCont cont_;
> };
>
>
> typedef Manager<char, int, std::map> Container;
>
> bool find42function (const Container::value_type& value)
> {
> return value == 42;
> }
>
> struct Find42functor
> : public std::unary_function<Container::value_type, bool>
> {
> bool operator () (const Container::value_type& value) const
> {
> return value == 42;
> }
> };
>
> int
> main ()
> {
> Container cont;
> cont.insert ('a', 42);
>
> // free function -------------------------------------------------------
> cont.find_if (&find42function);
>
> boost::function<bool (int)> func_1 (&find42function);
> cont.find_if (func_1);
>
> // Functor -------------------------------------------------------------
> cont.find_if (Find42functor());
>
> Find42functor functor;
> boost::function<bool (int)> func_2 (functor);
> cont.find_if (func_2);
>
> boost::function<bool (int)> func_3 = Find42functor();
> cont.find_if (func_3);
>
> boost::function<bool (int)> func_4 (Find42functor());
> //cont.find_if (func_4); // does not compile
> /* error message: ========================================================
> /d/vendor/include/boost/lambda/detail/function_adaptors.hpp: In static
> member function `static Result boost::lambda::function_adaptor<Result
> (*)(Arg1)>::apply(Result (*)(Arg1), A1&) [with RET = boost::function<bool
> ()(int), std::allocator<void> >, A1 = int, Arg1 = Find42functor (*)(),
> Result = boost::function<bool ()(int), std::allocator<void> >]':
> ...
> test.cpp:50: instantiated from `boost::optional<Value&> Manager<Key,
> Value, AssocContainer, Compare, Alloc>::find_if(Func) [with Func =
> boost::function<bool ()(int), std::allocator<void> > (*)(Find42functor
> (*)()), Key = char, Value = int, AssocContainer = std::map, Compare =
> std::less<char>, Alloc = std::allocator<std::pair<const char, int> >]'
> test.cpp:101: instantiated from here
> /d/vendor/include/boost/lambda/detail/function_adaptors.hpp:218: error:
> invalid conversion from `int' to `Find42functor (*)()'
>
> see error_func_4.txt for the entire error message
> ========================================================================*/
>
> // lambda --------------------------------------------------------------
> using boost::lambda::_1;
> boost::function<bool (int)> func_5 (_1 == 42);
> cont.find_if (func_5);
>
> //cont.find_if (_1 == 42.0); // does not compile

I solved this second error by using unlambda in the find_if method:

  template <typename Func>
  boost::optional<Value&> find_if (Func func)
  {
    using boost::lambda::_1;
    using boost::lambda::bind;
-> using boost::lambda::unlambda;

    typename AssocCont::iterator findResult =
      std::find_if (cont_.begin (), cont_.end (),
-> bind(unlambda(func),
                         bind(&AssocCont::value_type::second, _1)));
    if (findResult != cont_.end()) {
      return boost::optional<Value&> (findResult->second);
    }
    return boost::optional<Value&> ();
  }

But the other error still remains.

[snip]


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net