0

I have a function:

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

I can easily call it with either:

reader(&std::cin, out);

or

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

However, as soon as i attempt to create the thread from this function with either:

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

or

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

I get some weird errors along the lines of:

/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...>)

I have attempted to turn the function into a lambda, but that didn't help. I don't know what i'm doing wrong.

1 Answer 1

4

The error message is incredibly hard to parse, but here's a testcase:

#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)

And the problem is that you're passing out, but arguments to std::thread are copied and the copy (a temporary) cannot be bound to that std::string&.

You have to explicitly indicate that you wish to pass by reference:

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

Fixed testcase:

#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';
}

Output:

lol

(live demo)

(Note that I've dropped a ton of needless pointer usage from your example.)

Alternatively, drop the whole thing and use a lambda instead:

#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)

Sign up to request clarification or add additional context in comments.

5 Comments

I guess i'll have to sit down and read up on std::ref and other stuff like that. Didn't know about it.
@Volodya: What would be much superior would be to use a lambda instead.
I just did turn it into lambda, it helps with readability, but you still need the std::ref bit.
@Volodya: BTW please try to construct testcases like those in my answer in the future!
@Volodya: You would capture out and not have to pass it explicitly at all. I've added an example to the answer. Whether this is an appropriate technique for you depends on the rest of your program.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.