snk snk - 3 months ago 18
C++ Question

Use of std::vector::emplace_back

I have some class-warper for std::thread. Here is the constructor:

template <typename Function, typename... Args>
InterruptibleThread(Function&& fun, Args&&... args)
{
_thread = std::thread([](std::atomic_bool * f, Function&& function, Args&&... arguments)
{
_flag_ref = f;
(function)(std::forward<Args>(arguments)...);
},
&_flag,
std::forward<Function>(fun)
, std::forward<Args>(args)...
);
}


And then I'm using it so (example):
InterruptibleThread(&SourceImageList::StartFrameProcessingStatic, this, std::ref(it))

The compiler builds this code successfuly. But now I would like to make a vector of such objects:

std::vector<InterruptibleThread> grp;


I would like to allocate it on the stack so what I'm doing is:

grp.emplace_back(&SourceImageList::StartFrameProcessingStatic, this, std::ref(it));


And I'm getting this error:

C2064 term does not evaluate to a function taking 0 arguments


Here are the options which are validated by the compiler:

1) grp.push_back(new InterruptibleThread(&SourceImageList::StartFrameProcessingStatic, this, std::ref(it)));
2) grp.push_back(InterruptibleThread(&SourceImageList::StartFrameProcessingStatic, this, std::ref(it)));


But the first one is allocating an object on the heap so I need to release it manually, and the second one makes a copy of the object.

Can I use
emplace_back
here (compiler is MSVC 2015 update 3)?

Answer

You could modernize your code and pass a lambda into InterruptibleThread instead of passing a function and it's arguments (i.e. bind-style).

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

struct InterruptibleThread
{
    std::thread _thread;

    template <typename Function>
    InterruptibleThread(Function&& fun)
        : _thread(std::forward<Function>(fun))
    {
    }
};

struct Test
{
    std::vector<InterruptibleThread> grp;
    void test(int x) {
        grp.emplace_back([this, x]{ t1(x); }); // <==== HERE
    }
    void t1(int x) {
        std::cout << x << "\n";
    }
};

int main()
{
    Test t;
    t.test(5);
    t.grp[0]._thread.join();
}