Std :: bind assigned to std :: function

I need a type variable std::function<void(char**)>. Here is a simple example of giving up on this.

What I'm trying to understand is the following:

  • What does auto do that the compiler does not complain when I call jj_2a(5, 6)? This function has all the parameters associated with it.
  • But if I do not use auto, I get the behavior that I expect (compilation with arguments). Thus, it is clear that it function<void(void)>’s not at all what the car decided.
  • If I bind the first argument, not the second ( jj_3), then a call with two arguments works (but does not match the wrong argument, according to my mental model) when called with one argument (which, I think, should work) does not compile.
  • Using std::functionalfor jj_3_fsays "no viable conversion", although the error message does not help me yet.

See below for compiler and specific errors. This is linux, clang 3.8.0, ubuntu 16.04.1.

#include <functional>
#include <iostream>

void jj_1(int x, int y) { std::cout << x << ' ' << y << std::endl; }

int main() {
  using namespace std::placeholders; // for _1, _2, _3...

  auto jj_2a = std::bind(jj_1, 3, 2);
  jj_2a(5, 6);  // This works, prints "3 2", no compiler warning, is auto drunk?
  jj_2a();      // This also works, prints "3 2".
  std::function<void(void)> jj_2a_f = std::bind(jj_1, 30, 20);
  //jj_2a_f(50, 60);  // Compile error, good!
  jj_2a_f();  // This works, prints "30 20", good!

  auto jj_2b = std::bind(jj_1, _2, _1);
  jj_2b(5, 6);  // This works, prints "6 5", good.

  auto jj_3 = std::bind(jj_1, 3, _2);
  jj_3(5, 6);  // This works, prints "3 6", so it the first arg that is dropped!
  //jj_3(7);     // Compile error!

  //std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!
  //jj_4(11);
}

I will compile this with

clang++  -std=c++14 -Wall -Wextra /tmp/foo.cc -o /tmp/foo

Compiler related warnings are jj_3(7)as follows:

/tmp/foo.cc:21:7: error: no matching function for call to object of type 'std::_Bind<void (*(int,
  std::_Placeholder<2>))(int, int)>'
  jj_3(7);     // Compile error!
  ^~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1129:2: note: 
  candidate template ignored: substitution failure [with _Args = <int>]: no viable conversion from
  'std::_No_tuple_element' to 'int'
    operator()(_Args&&... __args)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1143:2: note: 
  candidate template ignored: substitution failure [with _Args = <int>]: no viable conversion from
  'std::_No_tuple_element' to 'int'
    operator()(_Args&&... __args) const
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1157:2: note: 
  candidate template ignored: substitution failure [with _Args = <int>]: no viable conversion from
  'std::_No_tuple_element' to 'int'
    operator()(_Args&&... __args) volatile
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1171:2: note: 
  candidate template ignored: substitution failure [with _Args = <int>]: no viable conversion from
  'std::_No_tuple_element' to 'int'
    operator()(_Args&&... __args) const volatile
    ^
1 error generated.

Compiler related warnings are jj_3_fas follows:

/tmp/foo.cc:23:32: error: no viable conversion from 'typename _Bind_helper<__is_socketlike<void (&)(int,
  int)>::value, void (&)(int, int), int, const _Placeholder<2> &>::type' (aka '_Bind<void (*(int,
  std::_Placeholder<2>))(int, int)>') to 'std::function<void (int)>'
  std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!
               ^        ~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:2008:7: note: 
  candidate constructor not viable: no known conversion from 'typename
  _Bind_helper<__is_socketlike<void (&)(int, int)>::value, void (&)(int, int), int, const
  _Placeholder<2> &>::type' (aka '_Bind<void (*(int, std::_Placeholder<2>))(int, int)>') to
  'nullptr_t' for 1st argument
  function(nullptr_t) noexcept
  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:2019:7: note: 
  candidate constructor not viable: no known conversion from 'typename
  _Bind_helper<__is_socketlike<void (&)(int, int)>::value, void (&)(int, int), int, const
  _Placeholder<2> &>::type' (aka '_Bind<void (*(int, std::_Placeholder<2>))(int, int)>') to 'const
  std::function<void (int)> &' for 1st argument
  function(const function& __x);
  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:2028:7: note: 
  candidate constructor not viable: no known conversion from 'typename
  _Bind_helper<__is_socketlike<void (&)(int, int)>::value, void (&)(int, int), int, const
  _Placeholder<2> &>::type' (aka '_Bind<void (*(int, std::_Placeholder<2>))(int, int)>') to
  'std::function<void (int)> &&' for 1st argument
  function(function&& __x) : _Function_base()
  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:2054:2: note: 
  candidate template ignored: substitution failure [with _Functor = std::_Bind<void (*(int,
  std::_Placeholder<2>))(int, int)>, $1 = void]: no type named 'type' in
  'std::result_of<std::_Bind<void (*(int, std::_Placeholder<2>))(int, int)> (int)>'
    function(_Functor);
    ^
1 error generated.

Fwiw, what I really want to do is parallel. I have a function

void MyFunction(A& a, B& b, const char** thing);

where Aand Bare class names. I have another function that expects a callback this way:

C DoStuff(const std::string& s, std::function<void(const char** thing)> f);

which then i try to call

DoStuff("Hello!", std::bind(MyFunction, an_a, a_b, _3));

and I get errors regarding the lack of a viable transformation.

+4
source share
4 answers

: , , bind, ?

, std::bind, std::function; , std::function ; , , .

- _2 () , , 2.

  • auto, , jj_2a (5, 6)? .

; .

  • auto, , ( ). , , .

; bind std::function, , ( ) std::function.

  • , (jj_3), ( , ) (, , ) t .

std::placeholders::_2, 2 . std::placeholders::_2 , , bind.

  • std:: functional jj_3_f " ", .

std::placeholders::_2, 2 ; std::function .

+6

:

 jj_3(7);     // Compile error!

, jj_3 . , , :

 jj_3(0, 7); // 0 is notused

jj_3 :

 auto jj_3 = std::bind(jj_1, 3, _1);

:

 std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!

, :

 std::function<void(int, int)> jj_3_f

, _2, , jj_3_f .

+2

std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!

std::function<void(int,int)> jj_3_f = std::bind(jj_1, 3, _2);

std::function<void(int,int)> jj_3_f = std::bind(jj_1, 3, _2);

:

 auto jj_3 = std::bind(jj_1, 3, _2);

auto jj_3 = std::bind(jj_1, 3, _1);

, _1

+1
source

Replace:

//std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!
//jj_4(11);

with:

std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _1);
jj_3_f(5);

A placeholder is the number of the parameter in the result function (one argument, then the first placeholder), and not the parameter in the "binded" function.

+1
source

Source: https://habr.com/ru/post/1650903/


All Articles