Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I create a vector of threads on the fly like this

Why is creation of vector of threads on the fly is wrong ? I am getting compilation error

C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory0(593): error C2280: 'std::thread::thread(const std::thread &)' : attempting to reference a deleted function

followed by a lot of other stuff.

#include <iostream>
#include <thread>
#include <vector>

using std::vector;
using std::thread;
using std::cout;

class obj_on_thread {
public:
    void operator()()
    {
        std::cout << "obj on thread\n";
    }
};

void function_on_thread() {
    std::cout << "function on thread\n";
}

auto named_lambda = []() { std::cout << "named_lambda_on_thread\n"; };

int main(){
    obj_on_thread obj;

    vector<thread> pool {
        thread{ obj },
        thread{ function_on_thread },
        thread{ named_lambda },
        thread{ []() { cout << "anonymous lambda on thread\n"; } }
    };
    cout << "main thread\n";

    for(auto& t : pool)
    {
        if (t.joinable())
        {
            cout << "Joinable = true";
            t.join(); //if called must be called once.
        }
        else
        {
            cout << "this shouldn't get printed, joinable = false\n";
        }
    }
    for (auto& t : pool)
    {
        if (t.joinable())
        {
            cout << " This won't be printed Joinable = true";
        }
        else
        {
            cout << "joinable = false thread are already joint\n";
        }
    }

    return 0;
}
like image 584
cpp_hex Avatar asked Nov 27 '14 10:11

cpp_hex


1 Answers

std::vector's constructor which uses initializer_list requires the elements to be copy-constructible, because initializer_list itself requires that (its underlying "storage" is implemented as a temporary array which is copy-constructed). std::thread is not copy-constructible (this constructor is deleted).

http://en.cppreference.com/w/cpp/utility/initializer_list

The underlying array is a temporary array, in which each element is copy-initialized...

There's no good way to solve this problem - you cannot initialize all your threads at once, but you can use (multiple calls, one for each thread - unfortunately):

  • emplace_back():

    pool.emplace_back(obj);
    
  • push_back() with rvalues:

    pool.push_back(thread{obj});
    
  • push_back() with explicit move()s:

    auto t = thread{obj};
    pool.push_back(std::move(t));
    
like image 161
Freddie Chopin Avatar answered Nov 15 '22 12:11

Freddie Chopin