Patrick Kelly
Patrick Kelly

Reputation: 1381

C++ Thread Error - compile-time error with class argument

I found the page C++ thread error: no type named type, with a similar error message to the one I am reporting below. The answer on that page doesn't cover this case, as best I can tell. Admittedly, there must be something simple that I am simply clueless about here.

I have been trying use threads in a C++ program I am working on. I had an initial version working with boost::thread without any problems. This morning, I tried to rewrite my code to use std::thread instead of boost::thread. That's when I suddenly ran into compile-time errors that I do not understand. I have reduced the problem to the following piece of code.

The upshot? As soon as I try to pass a reference to one of my own user-defined classes as a function argument, the program fails to compile.

#include <iostream>
#include <thread>

class TestClass { } ;

void testfunc1 ( void )           { std::cout << "Hello World TF1" << std::endl ; }
void testfunc2 ( double val )     { std::cout << "Hello World TF2" << std::endl ; }
void testfunc3 ( TestClass & tc ) { std::cout << "Hello World TF3" << std::endl ; }

int main ( int argc, char *argv[] )
{
    std::thread t1 ( testfunc1 ) ;

    double tv ;
    std::thread t2 ( testfunc2, tv ) ;

    TestClass tc ;
    std::thread t3 ( testfunc3, tc ) ;    //  compiler generates error here

    return 0 ;
}

The code will compile as long as I comment out that last line of code. When it is present, however, I get the following compile-time error.

$ g++ -std=c++11 test.cpp
In file included from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/thread:39:0,
                 from test.cpp:3:
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/functional: In instantiation of ‘struct std::_Bind_simple<void (*(TestClass))(TestClass&)>’:
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/thread:142:59:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(TestClass&); _Args = {TestClass&}]’
test.cpp:19:33:   required from here
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/functional:1505:61: error: no type named ‘type’ in ‘class std::result_of<void (*(TestClass))(TestClass&)>’
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/functional:1526:9: error: no type named ‘type’ in ‘class std::result_of<void (*(TestClass))(TestClass&)>’
         _M_invoke(_Index_tuple<_Indices...>)

There is clearly some kind of type-related issue, but I can't decipher this error message. Any idea what the issue is? (I happen to be using Cygwin on a Windows 10 machine, but I don't think that's relevant to the problem described.)

Upvotes: 1

Views: 865

Answers (2)

M&#225;rio Feroldi
M&#225;rio Feroldi

Reputation: 3591

That's because std::thread can't store C++ references, it's similar to how std::vector<T&> can't exist. So, in order to pass references around, there's a reference wrapper in the standard library. It's basically a pointer under the hood, which mimics some of the language-wise reference's behavior. The std::ref and std::cref (for const references) functions are used to create an object of std::reference_wrapper (they're convenient functions, as they have template type deduction and shorter names).

The only thing you have to add in your code is the std::ref function call, like so:

TestClass tc;
std::thread t3(testfunc3, std::ref(tc));

Upvotes: 2

Some programmer dude
Some programmer dude

Reputation: 409176

To pass references you need to use the std::ref wrapper:

std::thread t3 ( testfunc3, std::ref ( tc ) ) ;

Upvotes: 1

Related Questions