I have been trying to understand how std::bind works. So working up with different examples. Below is the sample program whose output i am unable to understand.
VERSION 1
class NAME
{
public:
void f()
{
std::cout<<"f"<<std::endl;
}
NAME()
{
std::cout<<"default constructor"<<std::endl;
}
NAME(const NAME&)
{
std::cout<<"copy constructor"<<std::endl;
}
};
int main()
{
std::cout << "Hello World" << std::endl;
NAME n;
std::function<void ()> callable = std::bind(&NAME::f, n);
return 0;
}
The output of the above version 1 is as follows:
Hello World
default constructor
copy constructor
copy constructor
I know that the argument passed will be copied, so the copy constructor should be called only one time but in the output above the copy constructor is called twice. Why/how is this happening? Is it because the new callable that is created using std::bind will be used to initialize another callable using std::function on the lhs?
VERSION 2
int main()
{
std::cout << "Hello World" << std::endl;
NAME n;
std::function<void ()> callable = std::move(std::bind(&NAME::f, n));
return 0;
}
The output of VERSION 2 is as follows:
Hello World
default constructor
copy constructor
copy constructor
copy constructor
In the output above(for version 2) when i use std::move, why/how is the copy constructor called thrice?
VERSION 3
int main()
{
std::cout << "Hello World" << std::endl;
NAME n;
auto callable = std::bind(&NAME::f, n);
return 0;
}
The output of version 3 is as follows:
Hello World
default constructor
copy constructor
In this case(version 3) why/how is the copy constructor called only once?
VERSION 4
int main()
{
std::cout << "Hello World" << std::endl;
NAME n;
auto callable = std::move(std::bind(&NAME::f, n));
return 0;
}
The output of version 4 is as follows:
Hello World
default constructor
copy constructor
copy constructor
What happens in this case(version 4) when we use auto
and std::move()
, why/how is the copy constructor called twice.
PS: The program is executed on an online compiler: Online compiler Used
Edit: Upon reading the comments i have a further question/doubt:
Question 1
If i use auto callable_1 = std::bind(&NAME::f, n);
and std::function<void ()> callable_2 = std::bind(&NAME::f, n);
then are the types of callable_1
and callable_2
different? If yes, then what is the type deduced by auto
for callable_1
? Or is it that the type deduced by auto
for callable_1
will be an unnamed class object just like for a lambda
.
Question 2
I have one further question: As i did in my case, if i pass n
instead of &n
in std::bind
then is the code legal? For example, if i write std::function<void ()> callable_1 = std::bind(&NAME::f, n);
and auto callable_2 = std::bind(&NAME::f, n);
then are both of these illegal? What if i passed ref(n)
instead of n
in both of these cases, then will they be illegal or legal?
Question 3
Are the statements auto callable = [&n]{n.f()};
and auto callable = std::bind(&NAME::f, cref(n));
equivalent(in functionality) and maybe in some other ways and is there any reason(advantage) to pick one over another apart from coding style?
Question 4
What if i write auto callable = std::bind(&NAME::f, 1_); callable(n); callable(std::ref(n));
. Is the statement callable(n)
illegal? And what about the statement callable(std::ref(n));
.