0

I am trying to use this lambda expression in my code. And looks like something's wrong with definition of functor or lambda.

I believe the lambda expression is true. but I can't satisfy the prototype of function I defined.

Function definition:

    template<typename E, typename container> 
void for_each(Iterator<E,container> begin, std::function<void(E&)> fun)
{
    do // does the given unary functor to elements 
    {  //from starting iterator 'til the end.
        fun(*begin);
        begin = begin.next();
    }while(begin.hasNext());

    fun(*begin);
}

And caller:

  for_each(c.iterator(), [&](E& e){add(e);});

I except achieve this function call with lambda expression. But compiler says "error: no matching function for call to .."

drh0use
  • 89
  • 5

2 Answers2

1

lambda is not std::function, so deduction fails.

You might simply pass generic Functor:

template<typename E, typename container, typename F> 
void for_each(Iterator<E, container> begin, F&& fun)
{
    // ...
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Ty, it worked. But I was trying to imitate this [link](https://stackoverflow.com/questions/20353210/usage-and-syntax-of-stdfunction) example. What part did I miss? – drh0use Dec 28 '18 at 23:23
  • Issue is with deduction, you might call it successfully `for_each(c.iterator(), [&](E& e){add(e);});` with your version. lambda can convert to `std::function`, but it is unrelated type. – Jarod42 Dec 28 '18 at 23:28
  • A curious decision to pass the function-object by reference instead of by value, like the standard-library does. If indirection is actually wanted, that's what `std::ref()` is for. – Deduplicator Dec 29 '18 at 16:22
  • @Deduplicator: pre-c++11, there are no forward references. now interfaces use them, for example [`std::invoke`](https://en.cppreference.com/w/cpp/utility/functional/invoke), [`std::thread`](https://en.cppreference.com/w/cpp/thread/thread/thread), ... (which still might use `std::reference_wrapper`). – Jarod42 Dec 29 '18 at 17:01
0

Issues with the code and Possible solution approaches below:

1. A Lambda expression is not std::function, it can only be stored in an object of type std::function.

Approach: (With your existing signature):

std::function<void()> f = []() -> void { // do something };
for_each(vec.begin(), vec.end(), f);

2. Better solution would be to use a Callable as a parameter (Go to end of the answer).

3. If you want to pull up your own version of for_each, why not follow the implementation that is consistent with other algorithms or for that matter with the implementation of for_each in the algorithm header.

Does all you want and is also consistent with other standard algorithms: en.cppreference.com/algorithms/for_each:

    template<class InputIt, class UnaryFunction>
    constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
    {
      for (; first != last; ++first) {
        f(*first);
      }
      return f;
    }
Raghu
  • 43
  • 1
  • 6
  • Using a forwarding reference isn't going to prevent you from being *"able to reuse the function object"* unless you `forward` the reference. And using an lvalue reference instead prevents you from calling your function with a lambda as an argument `for_each(x, y, [](...){...});`, which is not a good thing... – HolyBlackCat Dec 29 '18 at 16:15
  • @HolyBlackCat Incorporated the suggested changes. Must have sneaked in as I had to type it in due to some issues while copying. :p – Raghu Dec 29 '18 at 16:21