Home > other >  Why can we push function object to std::thread directly?
Why can we push function object to std::thread directly?

Time:09-10

I'm a little bit confuse about why we can do something like this:

std::vector<std::thread> vec;
vec.reserve(2);
vec.emplace_back(std::bind(silly, 1));
vec.emplace_back(std::bind(silly, 2));

for (auto i = 0; i < vec.size(); i  ) {
    vec[i].join();
}
// for folks who see this post after
// you can use push_back() like this:
vec.push_back(std::thread(std::bind(silly, 3)));

The code above, we push function object to thread vector directly, and I don't know why it is acceptable. Because from my knowledge thread vector could only push thread type object to it. Just like for a int vector, we could only push int type object to it.

The example below is what I can 100% understand, because we push thread object into thread vector!

std::vector<std::thread> vecOfThreads;
std::function<void()> func = []() {
    //Do Some Important Work
    // .....
    //Print Thread ID
    std::cout << "From Thread ID : " << std::this_thread::get_id() << "\n";
};
vecOfThreads.push_back(std::thread(func));
std::thread th1(func);
vecOfThreads.push_back(std::move(th1));
for (std::thread &th: vecOfThreads) {
    // If thread Object is Joinable then Join that thread.
    if (th.joinable())
        th.join();
}

Any explanation and suggested material for studying this part is appreciated!

CodePudding user response:

Edit: I missread code sample, as stated in comments, in this particular case of emplace_back, the constructor is called without going through the implicit conversion chain, as is the purpose of emplace_back. Leaving the rest nonetheless since question was about pushing.

C offers implicit conversions, which is what enables you to do thing like :

double a = 0;

Without getting an error due to assigning an int literal (0) to a double-type variable (a).

The above link can give you detailed explanation on implicit conversion, but that part that interest us is that :

A user-defined conversion consists of zero or one non-explicit single-argument converting constructor or non-explicit conversion function call

In std::thread documentation, there is a constructor that takes a std::function (and optionally its arguments), so it could be used to automagically convert functions into threads when pushing to thread vector, if the rest of the chain is respected (which apparently it isn't). In your code sample, it is directly called without implicit conversions limitations.

  • Related