1
votes

I have some homework, and I have troubles understanding, (probably) how passing parameters to std::thread constructor works.

Assume following code (I deleted unneeded parts)

template<typename T, typename Task>
class Scheduler
{
    private:
        typedef std::unordered_map<std::size_t, T> Results;
        class Solver
        {
            public:
            Solver(Task&& task) : m_thread(&Solver::thread_function, std::move(task))
            {
                m_thread.detach();
            }

            Solver(Solver&& solver) = default; // required for vector::emplace_back
            ~Solver() = default;

            private:
            void thread_function(Task&& task)
            {
                task();
            }
            std::thread m_thread;
        };

    public:
        Scheduler() = default;
        ~Scheduler() = default;

        void add_task(Task&& task)
        {
            m_solvers.emplace_back(std::move(task));
        }

    private:
        std::vector<Solver> m_solvers;
};

template<typename T>
struct Ftor
{
    explicit Ftor(const T& t) : data(t) { }
    T operator()() { std::cout << "Computed" << std::endl; return data; }
    T data;
};

int main()
{
    Scheduler<int, Ftor<int>> scheduler_ftor;
    Scheduler<int, std::function<int(void)>> scheduler_lambda;
    Ftor<int> s(5);
    scheduler_ftor.add_task(std::move(s));
    scheduler_lambda.add_task([](){ std::cout << "Computed" << std::endl; return 1; });
}

Why it doesn't compile? MVS2015 is complaining about

functional(1195): error C2064: term does not evaluate to a function taking 1 arguments functional(1195): note: class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
note: while compiling class template member function 'Scheduler<int,Ftor<int> >::Solver::Solver(Task &&)'

While G++ 4.9.2

functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’:
required from ‘void Scheduler<T, Task>::add_task(Task&&) [with T = int; Task = Ftor<int>]’

functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’ typedef typename result_of<_Callable(_Args...)>::type result_type;

I suppose there are some problems with std::moving to std::thread.

2
How is this question minimal? It looks like it the error in question could be produced from a far shorter and simpler code base. Go over every line of code and try to delete it. Here is an example of a far more minimal example that generates the same error without all the noise. I just looked at each line, thought "can I delete this", and I I could, I did it (maybe changing code elsewhere to match), and recompiled to ensure the bug still happened. -1. Include "aspirational" plans, but also include minimal code: noise gets in the way.Yakk - Adam Nevraumont

2 Answers

3
votes

If you use member function as first thread argument, second argument supposed to be this pointer, pointing to the object to which member function could be called to

UPDATE

Good discussion here

Start thread with member function

0
votes

I don't follow your code, but addressing the question, a extrapolated answer will be( most of the code is psuedocode) lets assume that there is a function int test(int name).

thread t0;
t0 = thread(test,32); 

thread t1(test,43);

Passing a argument to function.

int temp = 0;
int testfunc(int& q)
{
  cout<<q;
}

thread t1;
t1 = thread(testfunc,ref(temp));

In short, you just pass the name of the function that must be run in the thread as the first argument, and the functions parameters follow it in same order as they are in the function definition, for passing by reference you can use the ref() wrapper.See the below example.


#include <iostream>
#include <thread>
#include <string>
using namespace std;

void test(int a,int &a,string test)
{
  \\do something
}

int main()
{
     int test1 = 0;
     string tt = "hello";
     thread t1;
     t1 = thread(23,&test1,tt);
     t1.detach();
     return 0;
}

if you are wondering about the use of join() and detach(), refer to this thread: When should I use std::thread::detach?, refer to my answer post in that thread.