从这个函数创建线程时为什么会出错?

时间:2014-12-20 15:41:56

标签: c++ multithreading c++11

我有一个功能:

void reader (std::istream *in, std::string& out)
{
    (*in) >> out;
}

我可以用以下任何一种方式轻松调用它:

reader(&std::cin, out);

std::function<void(std::istream*, std::string&)> r = reader;
r(&std::cin, out);

但是,只要我尝试使用以下任一方法从此函数创建线程:

std::thread *reader = new std::thread(reader, &std::cin, out);

std::thread *reader = new std::thread(r, &std::cin, out);

我得到了一些奇怪的错误:

/usr/include/c++/4.8/functional: In instantiation of ‘struct std::_Bind_simple<std::function<void(std::basic_istream<char>*, std::basic_string<char>&)>(std::basic_istream<char>*, std::basic_string<char>)>’: /usr/include/c++/4.8/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with
_Callable = std::function<void(std::basic_istream<char>*, std::basic_string<char>&)>&; _Args = {std::basic_istream<char, std::char_traits<char> >*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&}]’ asyncinput.cpp:39:56:   required from here /usr/include/c++/4.8/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of<std::function<void(std::basic_istream<char>*, std::basic_string<char>&)>(std::basic_istream<char>*, std::basic_string<char>)>’
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^ /usr/include/c++/4.8/functional:1727:9: error: no type named ‘type’ in ‘class std::result_of<std::function<void(std::basic_istream<char>*, std::basic_string<char>&)>(std::basic_istream<char>*, std::basic_string<char>)>’
         _M_invoke(_Index_tuple<_Indices...>)

我试图将函数转换为lambda,但这没有帮助。我不知道我做错了什么。

1 个答案:

答案 0 :(得分:4)

错误信息非常难以解析,但这是一个测试用例:

#include <sstream>
#include <string>
#include <thread>
#include <iostream>

void reader (std::istream* in, std::string& out)
{
    (*in) >> out;
}

int main()
{
    std::function<void(std::istream*, std::string&)> r = reader;
    std::istringstream ss("lol");
    std::string out;

    std::thread t(reader, &ss, out);
    t.join();
    std::cout << out << '\n';
}

live demo

问题是您正在传递out,但是std::thread的参数被复制,副本(临时)不能绑定到std::string&

您必须明确表明您希望通过引用传递

std::thread t(reader, &ss, std::ref(out));
//                         ^^^^^^^^^   ^

修复了测试用例:

#include <sstream>
#include <string>
#include <thread>
#include <iostream>

void reader (std::istream* in, std::string& out)
{
    (*in) >> out;
}

int main()
{
    std::function<void(std::istream*, std::string&)> r = reader;
    std::istringstream ss("lol");
    std::string out;

    std::thread t(reader, &ss, std::ref(out));
    t.join();
    std::cout << out << '\n';
}

输出:

lol

live demo

(请注意,我已经从您的示例中删除了大量不必要的指针使用情况。)

或者,删除整个内容并改为使用lambda:

#include <sstream>
#include <string>
#include <thread>
#include <iostream>

int main()
{
    std::istringstream ss("lol");
    std::string out;

    std::thread t([&]() {
        ss >> out;
    });
    t.join();
    std::cout << out << '\n';
}

live demo