std::функция и std ::bind возвращают значение

#c #std-function #stdbind

#c #std-функция #stdbind

Вопрос:

Я пытаюсь понять, как работают std::bind и std::функция. Я не могу получить следующий код для компиляции:

 #include <iostream>
#include <string>
#include <functional>

void function(int a, float b, std::string const amp;s)
{
    std::cout << "printing function" << std::endl;
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    std::cout << s << std::endl;
}

int main(int argc, char *argv[])
{
    std::bind(amp;function, 10, 11.1, "hello")();
    std::function<void(int, float, std::string constamp;)> fun = std::bind(amp;function, 10, std::placeholders::_1, std::placeholders::_2);

    fun(0.2, "world");

    return 0;
}
  

компилятор жалуется, что:

 main.cpp: In function 'int main(int, char**)':
main.cpp:16:69: error: conversion from 'std::_Bind_helper<false, void (*)(int, float, const std::__cxx11::basic_string<char>amp;), int, const std::_Placeholder<1>amp;, const std::_Placeholder<2>amp;>::type {aka std::_Bind<void (*(int, std::_Placeholder<1>, std::_Placeholder<2>))(int, float, const std::__cxx11::basic_string<char>amp;)>}' to non-scalar type 'std::function<void(int, float, const std::__cxx11::basic_string<char>amp;)>' requested
  std::function<void(int, float, std::string constamp;)> fun = std::bind(amp;function, 10, std::placeholders::_1, std::placeholders::_2);
                                                            ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  

пожалуйста, кто-нибудь может объяснить? и как мне исправить эту ошибку?

Комментарии:

1. После того, как вы привязали a к 10 , остается только void(float, std::string constamp;) .

2. Также обратите внимание, что std::bind это не рекомендуется в C 17, и что использование lambda является более предпочтительным. auto fun = [](float a, std::string constamp; b) { function(10, a, b); };

3. Возможно, стоит отметить, что в современном коде лямбды всегда предпочтительнее, чем std::bind now.

4. @Zereges std::bind никоим образом не является устаревшим. std::bind1st и т.д. Устарели, но std::bind все еще имеют некоторые применения: sdowney.org/2017/06/why-stdbind-cant-be-formally-deprecated

5. @AlanBirtles Вы правы, я понятия не имею, почему я думал, что это устарело

Ответ №1:

Вы почти у цели, просто измените тип fun на

 std::function<void(float, std::string constamp;)> fun = std::bind(...);
//                ^^ no more int here

fun(0.2, "world");
//  ^^^^^^^^^^^^ those types must match the above signature
  

Обратите внимание, что вы меняете сигнатуру функции при исправлении первого аргумента функции типа int на значение 10 . Следовательно, это не может быть типом std::function экземпляра.

Далее обратите внимание, что Скотт Мейерс предлагает в пункте 34 «Эффективный современный C » заменить std::bind использование лямбдой, например

 auto fun = [](float b, std::string constamp; s){ function(10, b, s); };

// Identical invocation:
fun(0.2, "world");
  

Комментарии:

1. Я бы предложил использовать auto там.

2. @Zereges Это тоже устраняет проблему, но в первую очередь скрывает причину сбоя.

3. Я бы оставил объяснение как есть, но также предложил использовать auto вместо сложного возвращаемого типа.

4. Черт возьми, я опаздываю на 5 минут.