-1

Why does below code does not compile in Visual Studio 2015.

The same code works properly if ran on ideone.

class FooMutex
{
    std::mutex stm;
public:
    void foo() {}
};

int main()
{
    FooMutex o;
    std::thread t1(&FooMutex::foo, o);
}

Error is: C2664 'std::tuple<void (__thiscall FooMutex::* )(void),FooMutex>::
tuple(std::tuple<void (__thiscall FooMutex::* )(void),FooMutex> &&)'
: cannot convert argument 1 from 'void (__thiscall FooMutex::* )(void)' to 'std::allocator_arg_t'
Daemon
  • 1,575
  • 1
  • 17
  • 37

1 Answers1

0

There are multiple ways to do what you want:

  • Pass pointer instead: std::thread t1(&FooMutex::foo, &o);
  • Use std::bind: std::thread t1(std::bind(&FooMutex::foo, &o));
  • Use std::bind: std::thread t1(&FooMutex::foo, std::ref(o));
  • Use lambda function: std::thread t1([&o]() { o.foo(); });

The 3rd and 2nd ways are essentially the same as the 1st one. The 4th actually has the chance of being the most efficient one, since lambda will have smaller size than callable object that contains both pointer and member function pointer and thus has higher chance of being embedded into the internal std::function object, instead of being allocated on heap. Not that it changes anything, but still.

  • I do understand there are other ways of achieving it, but I wanted to understand why visual studio throws error and ideone does not. Is this particular code compiler dependent? Also if I remove std::mutex then it will compile fine. – Daemon May 30 '18 at 11:31
  • @Daemon Probably because you are using different compilers and one is buggy. `std::mutex` is a non-copyable and non-movable class, once to add it to your class, you class too becomes non-copyable and non-moveable. And without `std::mutex` it can be copied. –  May 30 '18 at 11:53
  • You can also use `std::ref(o)` to pass `o` by reference through `std::thread`'s constructor. – Quentin May 30 '18 at 12:17
  • @Ivan Is there a way to find that bug or to find more info on this. I am using Visual Studio 2015 – Daemon May 30 '18 at 13:27
  • @Daemon You need compiler that builds this code - it is wrong. Arguments should be copied or moved by `std::thread` constructor. If implementation doesn't do this, it is wrong. You can read how `std::thread` constructor works [here](http://en.cppreference.com/w/cpp/thread/thread/thread). BTW default compiler used by ideone does not build it. –  May 30 '18 at 13:34
  • @Ivan On ideone you have to choose C++14 – Daemon May 31 '18 at 03:59
  • @Daemon Cannot reproduce that. It doesn't build anywhere as it should. Might be a bug not with compiler itself, but with `std::mutex` implementation - probably someone forgot to disable copy/move constructors/assignments. –  May 31 '18 at 09:15
  • @Ivan The above error comes in Microsoft Visual studio Community Edition 2015. If I build the same code in ubuntu with g++ compiler -std=c++11 flag, in this case also i receive errors. If I use C++14 there is no error. – Daemon May 31 '18 at 17:50
  • @Daemon I don't have VS2015 on me, but [here](http://rextester.com/l/cpp_online_compiler_visual) VS2015 does not build your code, complaining about deleted copy constructor. Just fix your code. –  May 31 '18 at 20:12