std :: function как (не) постоянный входной параметр, отправленный & - PullRequest
2 голосов
/ 18 апреля 2020

Интересно, почему std::function<...(...)> & нужно указывать как const при передаче в качестве входного параметра функции. AFAIK нет способа изменить это, верно? Вот пример, который компилируется и работает нормально. Если я удаляю квалификатор const, я получаю ошибку:

#include <iostream>
#include <functional>

//int foo(std::function<int(int)> &f)
int foo(const std::function<int(int)> &f)
{
    return f(6);
}
int main(int argc, char **argv)
{
    auto f1 = [=](int i){ if (i<5) {return 8*2;} else {return 2;} };
    auto f2 = [=](int i){ if (i>3) {return i*i;} else {return 2;} };
    std::cout << foo(f1) << "\n";
}

Когда я использую объявление без const, я получаю следующую ошибку:

main.cpp: In function ‘int main(int, char**)’:
main.cpp:13:21: error: cannot bind non-const lvalue reference of type ‘std::function<int(int)>&’ to an rvalue of type ‘std::function<int(int)>’
  std::cout << foo(f1) << "\n";
                     ^
In file included from /usr/include/c++/7/functional:58:0,
                 from main.cpp:2:
/usr/include/c++/7/bits/std_function.h:685:7: note:   after user-defined conversion: std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = main(int, char**)::<lambda(int)>; <template-parameter-2-2> = void; <template-parameter-2-3> = void; _Res = int; _ArgTypes = {int}]
       function<_Res(_ArgTypes...)>::
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:4:5: note:   initializing argument 1 of ‘int foo(std::function<int(int)>&)’
 int foo(std::function<int(int)> &f)
     ^~~

1 Ответ

3 голосов
/ 18 апреля 2020

Лямбда - это не std::function, но из лямбды можно создать std::function. Когда вы передаете f1 или f2 в foo(), компилятор должен создать временный объект std::function, чтобы передать его параметру f. Однако ссылка lvalue на объект, отличный от const, не может быть привязана к временному объекту, в точности так, как говорится в сообщении об ошибке.

Чтобы разрешить передачу временного объекта, Параметр f необходимо изменить, чтобы он принимал std::function либо:

  • значение
  • lvalue ссылка на const объект
  • rvalue ссылка

В противном случае вы должны сами создать std::function в переменной, а затем передать вместо этого:

#include <iostream>
#include <functional>

//int foo(const std::function<int(int)> &f)
int foo(std::function<int(int)> &f)
{
    return f(6);
}

int main(int argc, char **argv)
{
    auto f1 = [=](int i){ if (i<5) {return 8*2;} else {return 2;} };
    auto f2 = [=](int i){ if (i>3) {return i*i;} else {return 2;} };
    std::function<int(int)> f = f1;
    std::cout << foo(f) << "\n";
}
...