julianmueller
julianmueller

Reputation: 131

invalid use of void expression with thread and an object

I want to create a thread of the function ahrs thats in my AHRS class. This function is in an infinite loop and calcs something the whole time and puts those calculations in variables. I want to pass those variables to my PID

int main() {

    AHRS* a = new AHRS();
    std::thread ahrs(a->ahrs());

    PID* p = new PID();
    float pitch;
    while(1) {
        pitch = a->getPitch();
        std::cout << "pitch: " << pitch << " pid: " << p->getError(0, pitch, 1) << std::endl;
        usleep(100000);
    }   
}

but i get the error

main_ahrs.cpp: In function ‘int main()’:
main_ahrs.cpp:26:28: error: invalid use of void expression

my ahrs.cpp looks like this:

#include "AHRS.h"

AHRS::AHRS() {
    //something
}

AHRS::~AHRS() {}

void AHRS::ahrs() {
    //something
    while(1) {
        //something
    }
}

float AHRS::getPitch() {
    //return something
}

float AHRS::getRoll() {
    //return something
}

float AHRS::getYaw() {
    //return something
}

thanks for your help

Upvotes: 2

Views: 6433

Answers (3)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

Lambda is your friend.

int main() {
  AHRS* a = new AHRS();
  std::thread ahrs(a->ahrs());

what the above does is it calls a->ahrs() (in main), takes its return value and passes it to the thread constructor. This isn't what you want.

Instead:

  AHRS* a = new AHRS();
  std::thread ahrs([a]{a->ahrs();});

will create a closure (or lambda) that consists of "do a call of a->ahrs()".

It then passes that closure to std::thread, which runs it on a different thread.

The [a] says "this is a closure, and it captures a (copy of) a". Then the body {a->ahrs();} says what the closure does.

In general, passing lambdas to std::thread is easier to reason about than passing the alternatives. There is a modest problem in that move-parameters require C++14 to work.

Using std::bind or the variardic constructor of std::thread are alternatives. I prefer passing code to passing data in this case, and passing a lambda closure is basically passing code.

Upvotes: 2

lvella
lvella

Reputation: 13443

Try like this:

#include <functional>

and then:

std::thread ahrs(std::bind(&AHRS::ahrs, a));

The way you are doing, you are calling the a->ahrs() method, that returns void. You must pass in to std::thread something that can be called: a function pointer, or something like that, not void.

In this case of my suggestion, you will pass to std::thread the return from std::bind, that is a callable object built with a pointer to the method and a pointer to the AHRS object.

Upvotes: 2

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

a->ahrs()

That is not how you name a function. That is how you call an expression and use its result for something. The result of the function is of void type (that is, there isn't one) so using this function call as an expression (and certainly for a function reference/object/handle/wrapper/pointer!) is just not going to work.

The function is called AHRS::ahrs.

A further complication is that it is a member function, so you have to bind the implicit this parameter, like so:

std::thread ahrs(std::bind(&AHRS::ahrs, a));

The binding creates a sort of pseudo-function reference that already has the first argument sorted out for you, so that you (or, in this case, the thread code, which has no ability or desire to guess what the object instance should be) does not need to.

Conveniently, thread can do the binding for you, though, so:

std::thread ahrs(&AHRS::ahrs, a);

should suffice.

Upvotes: 4

Related Questions