Is the result type of std::async too restrictive?

462 views
Skip to first unread message

Vicente J. Botet Escriba

unread,
Apr 2, 2013, 5:51:54 PM4/2/13
to std-dis...@isocpp.org
Hi,

I would like to know what should be the behavior of the following code

#include <thread>
#include <future>
void f1(int &) {}

void g1() {
std::future<void> f = std::async(f1, 1);
}


I'm getting some compiler errors (see below). IIUC this is expected
behavior of a compliant C++11 implementation.
Of course if I declare f1 as follows everything is OK.

void f1(int) {}

I'm wondering if the result type of std::async declaration isn't too
restrictive (due to the use of use of result_of)

template <class F, class... Args>
future<typename result_of<typename decay<F>::type(typename
decay<Args>::type...)>::type>
async(F&& f, Args&&... args);

The following declaration allow to compile first example without problems.

template <class F, class... Args>
auto async(F&& f, Args&&... args) -> std::future<decltype(f(args...))>;

Would it be a good idea to change this declaration on the C++ standard?

Best,
Vicente

------------
clang 3.2

../example/std_async_test.cpp:13:23: error: no matching function for
call to 'async'
std::future<void> f = std::async(f1, 1);
^~~~~~~~~~
/usr/include/c++/v1/future:2237:1: note: candidate template ignored:
substitution failure [with _Fp = int, _Args = <>]: no type named 'type'
in 'std::__1::__invoke_of<int, >'
async(launch __policy, _Fp&& __f, _Args&&... __args)
^
/usr/include/c++/v1/future:2254:1: note: candidate template ignored:
substitution failure [with _Fp = void (&)(int &), _Args = <int>]: no
type named 'type' in 'std::__1::__invoke_of<void (*)(int &), int>'
async(_Fp&& __f, _Args&&... __args)
^
1 error generated.

and for gcc-4.8.0

../example/std_async_test.cpp: In function �void g1()�:
../example/std_async_test.cpp:13:39: erreur: no matching function for
call to �async(void (&)(int&), int)�
std::future<void> f = std::async(f1, 1);
^
../example/std_async_test.cpp:13:39: note: candidates are:
In file included from ../example/std_async_test.cpp:8:0:
/usr/gcc-4.8/include/c++/4.8.0/future:1518:5: note: template<class _Fn,
class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes
...)>::type> std::async(std::launch, _Fn&&, _Args&& ...)
async(launch __policy, _Fn&& __fn, _Args&&... __args)
^
/usr/gcc-4.8/include/c++/4.8.0/future:1518:5: note: template argument
deduction/substitution failed:
../example/std_async_test.cpp:13:39: note: cannot convert �f1� (type
�void(int&)�) to type �std::launch�
std::future<void> f = std::async(f1, 1);
^
In file included from ../example/std_async_test.cpp:8:0:
/usr/gcc-4.8/include/c++/4.8.0/future:1538:5: note: template<class _Fn,
class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes
...)>::type> std::async(_Fn&&, _Args&& ...)
async(_Fn&& __fn, _Args&&... __args)
^
/usr/gcc-4.8/include/c++/4.8.0/future:1538:5: note: template argument
deduction/substitution failed:
/usr/gcc-4.8/include/c++/4.8.0/future: In substitution of
�template<class _Fn, class ... _Args> std::future<typename
std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&&
...) [with _Fn = void (&)(int&); _Args = {int}]�:
../example/std_async_test.cpp:13:39: required from here
/usr/gcc-4.8/include/c++/4.8.0/future:1538:5: erreur: no type named
�type� in �class std::result_of<void (&(int))(int&)>�



Lawrence Crowl

unread,
Apr 2, 2013, 6:13:06 PM4/2/13
to std-dis...@isocpp.org
On 4/2/13, Vicente J. Botet Escriba <vicent...@wanadoo.fr> wrote:
> I would like to know what should be the behavior of the following code
>
> #include <thread>
> #include <future>
> void f1(int &) {}
>
> void g1() {
> std::future<void> f = std::async(f1, 1);
> }

I would want an error. If the parameter is a writable reference,
it's likely the case that the programmer intends to return
information through that reference. We've lost that information
if the above compiles.
> ../example/std_async_test.cpp: In function ‘void g1()’:
> ../example/std_async_test.cpp:13:39: erreur: no matching function for
> call to ‘async(void (&)(int&), int)’
> std::future<void> f = std::async(f1, 1);
> ^
> ../example/std_async_test.cpp:13:39: note: candidates are:
> In file included from ../example/std_async_test.cpp:8:0:
> /usr/gcc-4.8/include/c++/4.8.0/future:1518:5: note: template<class _Fn,
> class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes
> ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...)
> async(launch __policy, _Fn&& __fn, _Args&&... __args)
> ^
> /usr/gcc-4.8/include/c++/4.8.0/future:1518:5: note: template argument
> deduction/substitution failed:
> ../example/std_async_test.cpp:13:39: note: cannot convert ‘f1’ (type
> ‘void(int&)’) to type ‘std::launch’
> std::future<void> f = std::async(f1, 1);
> ^
> In file included from ../example/std_async_test.cpp:8:0:
> /usr/gcc-4.8/include/c++/4.8.0/future:1538:5: note: template<class _Fn,
> class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes
> ...)>::type> std::async(_Fn&&, _Args&& ...)
> async(_Fn&& __fn, _Args&&... __args)
> ^
> /usr/gcc-4.8/include/c++/4.8.0/future:1538:5: note: template argument
> deduction/substitution failed:
> /usr/gcc-4.8/include/c++/4.8.0/future: In substitution of
> ‘template<class _Fn, class ... _Args> std::future<typename
> std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&&
> ...) [with _Fn = void (&)(int&); _Args = {int}]’:
> ../example/std_async_test.cpp:13:39: required from here
> /usr/gcc-4.8/include/c++/4.8.0/future:1538:5: erreur: no type named
> ‘type’ in ‘class std::result_of<void (&(int))(int&)>’
>
>
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Discussion" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-discussio...@isocpp.org.
> To post to this group, send email to std-dis...@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-discussion/?hl=en.
>
>
>


--
Lawrence Crowl

Vicente J. Botet Escriba

unread,
Apr 3, 2013, 7:14:09 AM4/3/13
to std-dis...@isocpp.org
Le 03/04/13 00:13, Lawrence Crowl a �crit :
> On 4/2/13, Vicente J. Botet Escriba <vicent...@wanadoo.fr> wrote:
>> I would like to know what should be the behavior of the following code
>>
>> #include <thread>
>> #include <future>
>> void f1(int &) {}
>>
>> void g1() {
>> std::future<void> f = std::async(f1, 1);
>> }
> I would want an error. If the parameter is a writable reference,
> it's likely the case that the programmer intends to return
> information through that reference. We've lost that information
> if the above compiles.
Sorry for the bad example. You are right, this should not compile as
f(1) doesn't compiles.
I have no a better one for the moment :(


Vicente

Vicente J. Botet Escriba

unread,
Apr 3, 2013, 7:39:46 AM4/3/13
to std-dis...@isocpp.org
Le 03/04/13 00:13, Lawrence Crowl a �crit :
> On 4/2/13, Vicente J. Botet Escriba <vicent...@wanadoo.fr> wrote:
>>
>> I'm getting some compiler errors (see below). IIUC this is expected
>> behavior of a compliant C++11 implementation.
>> Of course if I declare f1 as follows everything is OK.
>>
>> void f1(int) {}
>>
>> I'm wondering if the result type of std::async declaration isn't too
>> restrictive (due to the use of use of result_of)
>>
>> template <class F, class... Args>
>> future<typename result_of<typename decay<F>::type(typename
>> decay<Args>::type...)>::type>
>> async(F&& f, Args&&... args);
>>
>> The following declaration allow to compile first example without problems.
>>
>> template <class F, class... Args>
>> auto async(F&& f, Args&&... args) -> std::future<decltype(f(args...))>;
>>
>>
>>
>>
What are the difference between the declarations

template <class F, class... Args>
future<typename result_of<typename decay<F>::type(typename
decay<Args>::type...)>::type>
async(F&& f, Args&&... args);

and

template <class F, class... Args>
auto async(F&& f, Args&&... args) -> std::future<decltype(f(args...))>;


Best,
Vicente

Daniel Krügler

unread,
Apr 3, 2013, 7:44:45 AM4/3/13
to std-dis...@isocpp.org

2013/4/3 Vicente J. Botet Escriba <vicent...@wanadoo.fr>

What are the difference between the declarations


template <class F, class... Args>
future<typename result_of<typename decay<F>::type(typename
decay<Args>::type...)>::type>
async(F&& f, Args&&... args);

and


template <class F, class... Args>
auto async(F&& f, Args&&... args) -> std::future<decltype(f(args...))>;

I haven't checked everything, but you definitively have removed INVOKE support with your second form.

- Daniel

Daniel Krügler

unread,
Apr 3, 2013, 8:17:07 AM4/3/13
to std-dis...@isocpp.org
2013/4/3 Daniel Krügler <daniel....@gmail.com>

I have looked deeper in your proposal. This would clearly change the declaration of async in an incompatible way to the semantics of the code: Your transformation causes (among removal of full INVOKE support) all values (function object and arguments) to be provided as lvalues, but the specifications is intentionally defined to provide these values as rvalues via a std::move or decay_copy value transformation (see [futures.async] p3). The current specification is carefully designed such that the return type computation via result_of determines the value for the effective function object call.

For more details see the explanations given in the discussion of

http://cplusplus.github.com/LWG/lwg-defects.html#2021

- Daniel
Reply all
Reply to author
Forward
0 new messages