Связанная функция C ++ передана в лямбду - PullRequest
0 голосов
/ 04 октября 2018

У меня есть код ниже, где я пытаюсь напечатать таблицу умножения 10. Я связал функцию multiply с двумя параметрами 5 и 2.Я передаю связанную функцию для создания лямбды.И затем я пытаюсь передать лямбду в цикл for_each для печати таблицы умножения.Я интуитивно знаю, что, может быть, слишком далеко зашел.Но я не знаю точную причину.Может кто-нибудь объяснить.

#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;
}

Ошибка, которую я получаю, показана ниже.

/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...)>::
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

1 Ответ

0 голосов
/ 04 октября 2018

Я передаю функцию с двумя связанными и одним параметром-заполнителем.

Нет, это не так.Ваша лямбда выглядит так:

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

Это вызываемый объект, который вы передаете std::function.Теперь лямбда может вызываться только одним аргументом, а не тремя.Примечание:

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

Аналогично, f является вызываемым объектом только с одним параметром.Вы не можете вызывать его с тремя аргументами, потому что вы привязали два параметра к определенным значениям, поэтому для всех намерений и целей нет трех параметров.Может быть, это делает это более ясным:

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.

Итак, исправление заключается в изменении типа f1, чтобы отразить то, что вы на самом деле храните;вызываемое, которое принимает int и ничего не возвращает:

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