0

I have a compilation error when trying to instantiate a std::thread using decltype.I know of an workarround using lambdas, but i find it hard to understand what i am doing wrong. (maybe i am using decltype wrong).These reproduces on MSVC and GCC 8.1

#include<thread>

template<typename T>
class lockBasedQueue
{
private:
    std::queue<T> data_queue;
    mutable std::mutex m;
    std::condition_variable cond_var;

public:
    lockBasedQueue() {}
    void push(T newValue)
    {
        std::lock_guard<std::mutex> lk(m);
        data_queue.push(std::move(newValue));
        cond_var.notify_one();
    }

    void wait_and_pop(T& value)
    {
        std::unique_lock<std::mutex> lk(m);
        cond_var.wait(lk, [this]() {return data_queue.size() > 0; });
        value = std::move(data_queue.front());
        data_queue.pop();
    }

    bool empty() const
    {
        return false;
    }
};


int main()
{
    lockBasedQueue<int> q;
    std::thread t1(&lockBasedQueue<int>::push, q, 10);
    typedef decltype(q) myQueue;
    std::thread t2(&myQueue::empty, q);

    t1.join();
    t2.join();
    return 0;
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
eucristian
  • 391
  • 3
  • 17
  • 3
    [Cannot reproduce](http://rextester.com/NCCHP32416) with MSVC. – Passer By Jul 26 '18 at 15:04
  • apologies for the lack of public and include thread, i should have compiled the edited snippet before posting here. I have added the extra information. This seems to compile without errors on gcc, whereas on msvc this does not compile. From your point of view am i doing any non-standard shady stuff and depending on gcc? – eucristian Jul 26 '18 at 15:05
  • 2
    Add compiler error message(s) as well and compiler version – Slava Jul 26 '18 at 15:06
  • Edited the snippet a bit, i am doing something somewhere wrong, but it is just one of those days, when you are just too blind to see the obvious. Can you please try now and reproduce? – eucristian Jul 26 '18 at 15:10

1 Answers1

1

Your problem here is that your class contains a std::mutex and std::condition_variable. This makes your class non-copyable and non-moveable. That means

std::thread t1(&lockBasedQueue<int>::push, q, 10);

and

std::thread t2(&myQueue::empty, q);

will never work since you cant copy q into the thread.

What you can do though is use &q to get a pointer to q and then the thread can invoke the function pointer on that pointer. So, your code should be

int main()
{
    lockBasedQueue<int> q;
    std::thread t1(&lockBasedQueue<int>::push, &q, 10);
    typedef decltype(q) myQueue;
    std::thread t2(&myQueue::empty, &q);

    t1.join();
    t2.join();
    return 0;
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402