liv2hak
liv2hak

Reputation: 14970

C++ bound function passed to a lambda

I have the below code where I am trying to print the multiplication table of 10. I have bound the function multiply with two parameters 5 and 2. I am passing the bound function to create a lambda. And then I am attempting to pass the lambda to the for_each loop to print the Multiplication Table. I intutively kind of know that I may be pushing it a bit too far. But I don't know the exact reason. Can someone explain.

#include <iostream>
#include <vector>
#include <algorithm>
#include <thread>
#include <functional>
#include <future>
#include <array>
#include <unistd.h>

using namespace std;
using namespace std::placeholders;


int multiply(int a, int b, int c)
{
    return a*b*c;
}

int main()
{
    auto f = std::bind(multiply, 5, 2, _1);

    std::function<int(int,int,int)> f1 = [f](int a){cout << "Multiplication Table (10) :" << f(a) << endl; };

    vector<int> vec = {1,2,3,4,5,6,7,8,9,10};

    for_each(vec.begin(), vec.end(), f1);

    return 0;
}

The error that I am getting is shown below.

/home/karthik/Workspace/cpppen/learning/main.cpp: In function ‘int main()’:
/home/karthik/Workspace/cpppen/learning/main.cpp:26:107: error: conversion from ‘main()::<lambda(int)>’ to non-scalar type ‘std::function<int(int, int, int)>’ requested
     std::function<int(int,int,int)> f1 = [f](int a){cout << "Multiplication Table (10) :" << f(a) << endl;};
                                                                                                           ^
In file included from /usr/include/c++/7/algorithm:62:0,
                 from /home/karthik/Workspace/cpppen/learning/main.cpp:6:
/usr/include/c++/7/bits/stl_algo.h: In instantiation of ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Funct = std::function<int(int, int, int)>]’:
/home/karthik/Workspace/cpppen/learning/main.cpp:30:40:   required from here
/usr/include/c++/7/bits/stl_algo.h:3884:5: error: no match for call to ‘(std::function<int(int, int, int)>) (int&)’
  __f(*__first);
  ~~~^~~~~~~~~~
In file included from /usr/include/c++/7/functional:58:0,
                 from /home/karthik/Workspace/cpppen/learning/main.cpp:8:
/usr/include/c++/7/bits/std_function.h:701:5: note: candidate: _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int, int, int}]
     function<_Res(_ArgTypes...)>::
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

Upvotes: 0

Views: 518

Answers (1)

Rakete1111
Rakete1111

Reputation: 48938

I am passing a function with two bound and one placeholder parameter.

No you're not. Your lambda looks like this:

[f](int a) {
    cout << "Multiplication Table (10) :" << f(a) << endl;
}

That is the callable object that you are passing to std::function. Now, the lambda is callable with only one argument, not three. Notice:

[/*...*/](int a){ /*...*/ }
//        ^^^^^
//      one parameter

Likewise, f is a callable object with only one parameter. You can't call it with three arguments, because you've bound two parameters to specific values, so, for all intents and purposes, there are no three parameters. Maybe this makes it more clear:

auto add = [](int a, int b) { return a + b; };
auto addTo5 = [&add](int a) { return add(a, 5); };

add(1, 2); // ok, lambda takes two parameters
addTo5(3); // ok, lambda takes one parameter
addTo5(1, 2); // not ok, lambda doesn't take two parameters

std::function<int(int, int)> fadd = add; // ok
std::function<int(int)> faddTo5 = addTo5; // ok
std::function<int(int, int)> faddTo5fail = addTo5; // not ok, same reason

// addTo5 is approximately what std::bind does: It generates an object which has
// several variables "fixed", and so only takes the placeholder arguments that aren't
// specified.

So, the fix is to change f1's type to reflect what you are actually storing; a callable that takes an int and returns nothing:

std::function<void(int)> f1 = /*...*/;
//            ^^^^
//          lambda returns nothing

Upvotes: 1

Related Questions