Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I use reference in std::future parameters

Tags:

c++

c++11

c++14

Why does the following code (on Ideone) give me an error?

#include <future>
#include <iostream>
#include <string>

int main()
{
    int foo = 0;
    bool bar = false;
    std::future<std::string> async_request = std::async(
        std::launch::async,
        [=, &foo](bool& is_pumping_request) -> std::string {
            return "str";
        },
        bar
    );
    std::cout << async_request.get() << std::endl;
}

Output:

In file included from /usr/include/c++/5/future:38:0,
                 from prog.cpp:1:
/usr/include/c++/5/functional: In instantiation of 'struct std::_Bind_simple<main()::<lambda(bool&)>(bool)>':
/usr/include/c++/5/future:1709:67:   required from 'std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = main()::<lambda(bool&)>; _Args = {bool&}; typename std::result_of<_Functor(_ArgTypes ...)>::type = std::basic_string<char>]'
prog.cpp:15:2:   required from here
/usr/include/c++/5/functional:1505:61: error: no type named 'type' in 'class std::result_of<main()::<lambda(bool&)>(bool)>'
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
/usr/include/c++/5/functional:1526:9: error: no type named 'type' in 'class std::result_of<main()::<lambda(bool&)>(bool)>'
         _M_invoke(_Index_tuple<_Indices...>)
         ^

However, if I change bool& to bool in the parameters list, it compiles successfully.

Why?

like image 427
FrozenHeart Avatar asked Dec 08 '16 14:12

FrozenHeart


1 Answers

Like std::thread, std::asyc passes the parameters by value to the "function". If you have a function that takes a reference you need to wrap the variable you are passing to asyc with std::ref like

#include <future>
#include <iostream>
#include <string>

int main()
{
    int foo = 0;
    bool bar = false;
    std::future<std::string> async_request = std::async(
        std::launch::async,
        [=, &foo](bool& is_pumping_request) -> std::string {
            return "str";
        },
        std::ref(bar)
    );
    std::cout << async_request.get() << std::endl;
}

Live Example

If the function takes a const & then you need to use std::cref.

like image 67
NathanOliver Avatar answered Oct 14 '22 00:10

NathanOliver