Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I std::bind successfully with the wrong parameters?

Tags:

c++

c++11

stdbind

#include <iostream>
#include <functional>

using callback = std::function<void(int, void*)>;

void AddCallback(callback cb) {}

void foo(int i) {}

int main() {
  auto f = std::bind(&foo, std::placeholders::_1);
  AddCallback(f);
}

I tried the code with g++ 9.3.0 and clang++ 10.0.0, they both compiled ends no errors.

Is the type of bind result and callback the same type? One is std::function<void(int, void*)>, the other is something equal to std::function<void(int)>? Why can I call AddCallback() with different types?

like image 760
Xingx1 Avatar asked Jul 03 '20 08:07

Xingx1


People also ask

What does std :: bind do in C++?

std::bind is a Standard Function Objects that acts as a Functional Adaptor i.e. it takes a function as input and returns a new function Object as an output with with one or more of the arguments of passed function bound or rearranged.

Is std :: bind deprecated?

Yes: std::bind should be replaced by lambda For almost all cases, std::bind should be replaced by a lambda expression. It's idiomatic, and results in better code.

Does STD bind allocate?

As far as I can tell std::bind just concatenates stuff together into an object, so binding anything to a member function will result in an object that is at least three pointers in size. Assigning this object to a std::function will result in dynamic memory allocation.

How does STD bind work?

std::bind allows you to create a std::function object that acts as a wrapper for the target function (or Callable object). std::bind also allows you to keep specific arguments at fixed values while leaving other arguments variable.

How do you bind arguments in C++ without reference?

The arguments to bind are copied or moved, and are never passed by reference unless wrapped in std::ref or std::cref. Duplicate placeholders in the same bind expression (multiple _1 's for example) are allowed, but the results are only well defined if the corresponding argument (u1) is an lvalue or non-movable rvalue.

Can you have multiple arguments in the same bind statement?

The arguments to bind are copied or moved, and are never passed by reference unless wrapped in std::ref or std::cref . Duplicate placeholders in the same bind expression (multiple _1 's for example) are allowed, but the results are only well defined if the corresponding argument ( u1) is an lvalue or non-movable rvalue.

What is the return type of std::bind?

The return type of std::bind is CopyConstructible if all of its member objects (specified above) are CopyConstructible, and is MoveConstructible otherwise. The type defines the following members:

What are the placeholder arguments of a bind subexpression?

If the bind subexpression has any placeholder arguments, they are shared with the outer bind (picked out of u1, u2, ... ). Specifically, the argument vn in the std::invoke call above is arg (std::forward<Uj> (uj)...) and the type Vn in the same call is std::result_of_t<T cv &(Uj&&...)>&& (cv qualification is the same as that of g ).


1 Answers

It seems you can pass more arguments to the result of bind than necessary, and they will be silently ignored.

If some of the arguments that are supplied in the call to [the result of bind] are not matched by any placeholders ..., the unused arguments are evaluated and discarded.

— cppreference

like image 56
HolyBlackCat Avatar answered Sep 18 '22 04:09

HolyBlackCat