Marco Belli
Marco Belli

Reputation: 103

c++11 std::move thread function

I'm trying to make this piece of code work but i can't understood where I'm wrong the following code won't print the "foo" and the "here I'm" strings

class scoped_thread
{
std::thread t;
public:
explicit scoped_thread(std::thread t_):t(std::move(t_))
{
    std::cout<<"here I'm"<<std::endl;
    if(!t.joinable())
        throw std::logic_error("No thread");
}

~scoped_thread()
{

    t.join();
}

scoped_thread(scoped_thread const&)=delete;
scoped_thread& operator=(scoped_thread const&)=delete;
};


void foo(){
std::cout<<"foo"<<std::endl;    
}

scoped_thread t1(std::thread(foo));

it simply won't execute the constructor.

if I change the last lines to

class foo1{
public:
void foo(){
    std::cout<<"foo"<<std::endl;    
}

}

scoped_thread t1(std::thread(&foo1::foo,&foo1));

the thread foo start to work.

i'm using mingw 4.8.1 and c++11 flag of the compiler where I'm wrong? I'have tried to figure what constructor must I use but up to now I haven't found it

Upvotes: 1

Views: 269

Answers (1)

R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234654

This is known as the Most Vexing Parse.

Basically the compiler treats scoped_thread t1(std::thread(foo)); as a function declaration (declaring a function with a single std::thread argument named foo). It can be either a function declaration or a variable definition, but the rules of the language state that anything that can be both is a function declaration.

The traditional fix has been to add extra parentheses, like so scoped_thread t1((std::thread(foo))); making it so that it cannot be parsed as a function declaration anymore. With C++ you can also use list-initialization instead, which doesn't fall prey to the Most Vexing Parse (though it has its own issues), like so scoped_thread t1{std::thread(foo)};.

Upvotes: 1

Related Questions