0

I have a class B that contains an internal class A. The class A has a method that needs to access some members of B, so it has as one argumet a reference to the external class and one other argument. Now i would like to start this method in another thread from B.

I know this might be a duplicate of this question: Start thread with member function But my following minimal example isn't compiling. It sais:

Error C2672 "std::invoke": No matching overloaded function found.

Error C2893 Failed to specialize function template "unknown-type std::invoke(_Callable &&,_Types &&...) noexcept(<expr>)".

This might be related to the pass by reference, but using std::ref does not help me at all.

B.h

#include <thread>

class B
{
public:
    class A
    {
     public:
        int member_a;
    
        A(int member);
        void calc(B& b, int factor);
        std::thread thread_starting_wrapper(B& b, int factor);
    };

    int member_b;
    std::thread myTread;
    A* myA;

    B();
    std::thread start_thread();
    std::thread start_thread_wrapper();
};

B.cpp

#include "B.h"
#include <iostream>


B::B()
{
    member_b = 10;
    myTread = std::thread(nullptr);
    myA = new A(5);
}

B::A::A(int member)
{
    member_a = member;
}


void B::A::calc(B& b, int factor)
{
     std::cout << (b.member_b + member_a) * factor << std::endl;
}

std::thread B::start_thread()
{
    return std::thread(&B::A::calc, myA, std::ref(*this), 2);
    // return std::thread([this] { this->myA->calc(std::ref(*this), 2); } );
}

std::thread B::A::thread_starting_wrapper(B& b, int factor)
{
    return std::thread([&] {calc(std::ref(b), factor);});
}

std::thread B::start_thread_wrapper()
{
     return this->myA->thread_starting_wrapper(std::ref(*this), 2);
}

main.cpp

#include "B.h"

int main()
{
    B* b = new B();
    std::thread t = b->start_thread();
    //std::thread t2 = b->start_thread_wrapper();
    t.join();
}

Neither using the lambda version nor wrapping the function into A helps. What am I missing?

S. Vogt
  • 375
  • 2
  • 9
  • `std::thread(&B::A::calc, myA, std::ref(*this), 2);` you want to `Calc` for A instance, not B. – rafix07 Feb 23 '21 at 10:39
  • 2
    "isn't compiling" - so show the compile error. Why do you expect people to guess? – Useless Feb 23 '21 at 10:45
  • Was trying different ways in doing the same. – S. Vogt Feb 23 '21 at 10:54
  • 1
    What is this supposed to do: `myTread = std::thread(nullptr);`? Try making your constructor like this instead: `B::B() : member_b{10}, myTread{}, myA{new A(5)} {}` – Ted Lyngmo Feb 23 '21 at 10:57
  • I commented it out before compiling, even if i think it would not be compiled at all. – S. Vogt Feb 23 '21 at 11:00
  • 1
    `myTread = std::thread(nullptr);` is probably the reason for your compilation error - but you have more errors in the code as can be seen [here](https://godbolt.org/z/7c4hPE) when using the address sanitizer. – Ted Lyngmo Feb 23 '21 at 11:01
  • 1
    You are rigth. The ```std::thread(nullptr);``` caused it. You can make a answer out of it. Thanks for that. I was totally focused on the other part of the code. – S. Vogt Feb 23 '21 at 11:02

1 Answers1

1

You are trying to pass nullptr to the std::thread constructor in B::B():

myTread = std::thread(nullptr);

Rewritten it to use the member initializer list and to let std::thread be default constructed it could look like this:

B::B() : member_b{10}, myTread{}, myA{new A(5)} {}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108