duncster94
duncster94

Reputation: 598

"no matching function call" error when multithreading in C++

I'm failing to understand what I've done wrong. I've gone through several examples as well as the cppreference and come up with nothing.

When I try to execute a number of threads using a for loop, I call a function "evaluate". When I run the program in series there is no compiling problem, however adding multithreading yields the following:

GraphEvaluate.cpp:35:70: error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, const std::vector<std::vector<double> >&, const std::vector<InVec>&, InVec&, Graph&)’
   t[iii] = std::thread(evaluate, controlSpace, stateSpace, box, graph);

I don't understand how "evaluate" is an 'unresolved overloaded function type'.

Here is the code:

...
std::thread t[g_threads-1];


int counter(0);


for(int iii = 0 ; iii < (g_threads - 1) ; ++iii)
{
    InVec box(stateSpace.at(counter));
    t[iii] = std::thread(evaluate, controlSpace, stateSpace, box, graph);
    counter += 1;
}


for(int iii = 0 ; iii < (g_threads - 1) ; ++iii)
{
    t[iii].join();
}
...

And the evaluate function:

void evaluate(const std::vector<std::vector<double>> &controlSpace, 
    const std::vector<InVec> &stateSpace, InVec box, Graph &graph)
{
    std::vector<InVec> boxList;  // create empty vector of InVec objects
    SPnode ASP(box);             // create subpaving node with box
    mince(ASP, g_epsilon);       // mince box
    treeToList(ASP, boxList);    // convert tree to list for efficient mapping


    // map each box in boxList with mapping defined in GraphMapping.cpp for each
    // controller value
    for (auto control : controlSpace)
    {
        ImList imageList;

        for (auto box : boxList)
        {
            imageList.addBox(mapping(box, control));
        }

        InVec intersectionBox(inclusionMap(imageList));
        std::vector<InVec> intersectingBoxes;  // list of boxes in state space
        // that intersect with intersectionBox

        for (auto ssBox : stateSpace)
        {
            if (!(noIntersection(ssBox, intersectionBox))) 
                intersectingBoxes.push_back(ssBox);
        }


        std::vector<int> nodeList; // list of nodes that box (function input)
        // points to with the given control

        if (!(intersectingBoxes.empty()))
        {
            for (auto ssBox : intersectingBoxes)
            {
                for (auto image : imageList.getList())
                {
                    if (!(noIntersection(ssBox, image)))
                    {
                        nodeList.push_back(ssBox.getBoxNumber());
                        break;
                    }
                }
            }
        }


        if (!(nodeList.empty()))
        {
            for (auto node : nodeList)
            {
                graph.setAdjList(box.getBoxNumber(), Edge(node, control));
            }
        }
    }
}

Any help is appreciated.

Upvotes: 1

Views: 1181

Answers (1)

chema989
chema989

Reputation: 4172

The constructor of std::thread deduces its argument types and stores them by value.

C++ template function argument type deduction mechanism deduces type T from an argument of type T&. Hence, all arguments to std::thread are passed by value. @MaximEgorushkin

If you need to call a function that its arguments are references from a std::thread, wrap the argument using std::ref(). For example:

std::thread(evaluate, std::ref(controlSpace), std::ref(stateSpace), box, std::ref(graph));

On the other hand, you need to change the declaration of evaluate function like:

void evaluate(std::vector<std::vector<double>> controlSpace, 
    std::vector<InVec> stateSpace, InVec box, Graph graph);

For more information, see this post.

Upvotes: 2

Related Questions