函数返回一个可中断的线程

时间:2018-01-21 20:47:13

标签: c++ c++11

我问previous question有关创建一个函数,该函数指定一个线程与其参数一起运行的函数,我希望将一个重载函数的名称作为我的线程运行的函数传递,并且线程根据我传递的参数类型选择合适的线程。例如:

void MyThreadFunc(CObject& obj) {}  // Should be called when passing an lvalue
void MyThreadFunc(CObject&& obj) {} // Should be called when passing an rvalue

答案是我应该在调用我的线程创建函数时指定我的线程应该作为模板参数运行的函数的类型:

template<typename FunctionType, typename ...Args>
void StartDetachedThread(FunctionType func, Args&&... args)
{
    thread([&]()
    {
        func(forward<Args>(args)...);
    }).detach();
}

CObject object;
StartDetachedThread<void (CObject&)>(MyThreadFunc, std::ref(object)); // Calls MyThreadFunc(CObject&)

CObject object2;
StartDetachedThread<void (CObject&&)>(MyThreadFunc, std::move(object2)); // Calls MyThreadFunc(CObject&&)

我明白了。然后我将这些知识带入了一个可中断的线程实现,这个实现是我从这个站点上发现的片段构建的,但是遇到了障碍。这是我修剪过的线程类:

#include <iostream>
#include <thread>
#include <future>

using namespace std;

class interruptible_thread
{
    std::thread m_threadInternal;
public:

    template<typename FunctionType, typename... Args>
    interruptible_thread(FunctionType&& f, Args&&... args) 
    {
        m_threadInternal = std::thread([&]
        (typename std::decay<FunctionType>::type&& f
            , typename std::decay<Args>::type&&... args)
        {
            f(std::forward<Args>(args)...);            /// ***** COMPILER ERROR HERE
        }
            , std::forward<FunctionType>(f)
            , std::forward<Args>(args)...);
    }
    ~interruptible_thread() {}
    interruptible_thread(interruptible_thread&& rhs) { m_threadInternal = std::move(rhs.m_threadInternal); }
};

class CObject {};
void MyThreadFunc(CObject& obj) {}
void MyThreadFunc(CObject&& obj) {}

template<typename FunctionType, typename... Args>
interruptible_thread CreateThread(FunctionType&& f, Args&&... args)
{
    return interruptible_thread(f, args...);
}

我知道在构建interruptible_thread时我无法指定模板参数,所以写CreateThread()为我做这个。但是,当我编码

CObject o2;
interruptible_thread thr = CreateThread<void (CObject&&)>(MyThreadFunc, std::move(o2));

VS 2017抱怨上述行:

'void (CObject &&)': cannot convert argument 1 from 'CObject' to 'CObject &&'
You cannot bind an lvalue to an rvalue reference

现在,我可能已经看了太久了,但我不明白这个问题。有人可以轻轻解释一下吗?

1 个答案:

答案 0 :(得分:1)

您忘了完善前方args内的CreateThread()

template<typename FunctionType, typename... Args>
interruptible_thread CreateThread(FunctionType&& f, Args&&... args)
{
  return interruptible_thread(std::forward<FunctionType>(f), std::forward<Args>(args)...);
}

如果你不这样做,那么args将从rvalue变为左值引用,以便传递给interruptible_thread,这将无效。

另请注意:避免在Visual Studio中使用名称CreateThread,已经存在名为CreateThread的WinAPI,这可能会导致冲突。