【问题标题】:C++11 std::thread accepting function with rvalue parameterC++11 std::thread 接受带有右值参数的函数
【发布时间】:2015-07-09 02:08:45
【问题描述】:

我有一些作业,但我很难理解(可能)将参数传递给 std::thread 构造函数的工作原理。

假设以下代码(我删除了不需要的部分)

template<typename T, typename Task>
class Scheduler
{
    private:
        typedef std::unordered_map<std::size_t, T> Results;
        class Solver
        {
            public:
            Solver(Task&& task) : m_thread(&Solver::thread_function, std::move(task))
            {
                m_thread.detach();
            }

            Solver(Solver&& solver) = default; // required for vector::emplace_back
            ~Solver() = default;

            private:
            void thread_function(Task&& task)
            {
                task();
            }
            std::thread m_thread;
        };

    public:
        Scheduler() = default;
        ~Scheduler() = default;

        void add_task(Task&& task)
        {
            m_solvers.emplace_back(std::move(task));
        }

    private:
        std::vector<Solver> m_solvers;
};

template<typename T>
struct Ftor
{
    explicit Ftor(const T& t) : data(t) { }
    T operator()() { std::cout << "Computed" << std::endl; return data; }
    T data;
};

int main()
{
    Scheduler<int, Ftor<int>> scheduler_ftor;
    Scheduler<int, std::function<int(void)>> scheduler_lambda;
    Ftor<int> s(5);
    scheduler_ftor.add_task(std::move(s));
    scheduler_lambda.add_task([](){ std::cout << "Computed" << std::endl; return 1; });
}

为什么它不编译? MVS2015在抱怨

functional(1195): error C2064: term 不计算为带 1 个参数的函数 功能(1195):注意:类没有定义一个'operator()'或用户定义的转换运算符到一个指向函数的指针或引用到函数,需要适当数量的参数
注意:在编译类模板成员函数'Scheduler >::Solver::Solver(Task &&)'时

虽然 G++ 4.9.2

功能:在 'struct std::_Bind_simple<:_mem_fn ftor> >::Solver::*)(Ftor&&)>(Ftor)>':
'void Scheduler::add_task(Task&&) [with T = int;任务 = Ftor]'

functional:1665:61: error: no type named 'type' in 'class std::result_of<:_mem_fn ftor> >::Solver::*)(Ftor &&)>(Ftor)>' typedef typename result_of<_callable>::type result_type;

我认为 std::moving 到 std::thread 存在一些问题。

【问题讨论】:

  • 这个问题最小吗?看起来有问题的错误可能是由更短和更简单的代码库产生的。检查每一行代码并尝试删除它。 Here is an example of a far more minimal example that generates the same error 没有噪音。我只是看着每一行,想“我可以删除这个吗”,我可以,我做到了(也许更改其他地方的代码以匹配),并重新编译以确保错误仍然发生。 -1。包括“有抱负的”计划,但也包括最少的代码:噪音会阻碍。

标签: multithreading c++11


【解决方案1】:

如果你使用成员函数作为第一个线程参数,第二个参数应该是this指针,指向可以调用成员函数的对象

更新

这里讨论得很好

Start thread with member function

【讨论】:

  • 问题的另一部分是?如果您不想分享您的想法,您为什么要发表评论。
  • @Zereges 在接受之前,您是否确认此解决方案在 gcc 和 MSVC 上都解决了您的问题?我敢打赌它不会在 MSVC2013 中工作,我不知道他们是否修复了一个错误,特别是在 MSVC2015 中会导致您的代码无法工作的错误。
  • 我在 MSVC2015 以及 GCC 中都对其进行了测试,并且成功了。
  • @Zereges 很酷,很高兴它成功了。顺便说一句,VC2015 RC 刚刚发布
  • @Yakk MSVC2015 RC 今天刚刚发布。请检查并告诉我们此错误是否已修复?谢谢
【解决方案2】:

我没有按照你的代码,但是解决问题,一个推断的答案将是(大部分代码是psuedocode) 假设有一个函数 int test(int name)

thread t0;
t0 = thread(test,32); 

thread t1(test,43);

将参数传递给函数。

int temp = 0;
int testfunc(int& q)
{
  cout<<q;
}

thread t1;
t1 = thread(testfunc,ref(temp));

简而言之,您只需将必须在 线程 中运行的 函数名称 作为 第一个参数,然后将 函数参数按照与函数定义中相同的顺序跟随它,为了通过引用传递,您可以使用ref()包装器。参见下面的例子。


#include <iostream>
#include <thread>
#include <string>
using namespace std;

void test(int a,int &a,string test)
{
  \\do something
}

int main()
{
     int test1 = 0;
     string tt = "hello";
     thread t1;
     t1 = thread(23,&test1,tt);
     t1.detach();
     return 0;
}

如果您对join()detach() 的使用有疑问,请参阅此主题:When should I use std::thread::detach?,请参阅我在该主题中的回答帖子。

【讨论】:

    猜你喜欢
    • 2017-02-20
    • 1970-01-01
    • 2016-04-02
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    相关资源
    最近更新 更多