[PATCH] PR libstdc++/91456 make INVOKE<R> work with uncopyable prvalues

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

[PATCH] PR libstdc++/91456 make INVOKE<R> work with uncopyable prvalues

Jonathan Wakely-3
In C++17 a function can return a prvalue of a type that cannot be moved
or copied. The current implementation of std::is_invocable_r uses
std::is_convertible to test the conversion to R required by INVOKE<R>.
That fails for non-copyable prvalues, because std::is_convertible is
defined in terms of std::declval which uses std::add_rvalue_reference.
In C++17 conversion from R to R involves no copies and so is not the
same as conversion from R&& to R.

This commit changes std::is_invocable_r to check the conversion without
using std::is_convertible.

std::function also contains a similar check using std::is_convertible,
which can be fixed by simply reusing std::is_invocable_r (but because
std::is_invocable_r is not defined for C++11 it uses the underlying
std::__is_invocable_impl trait directly).

        PR libstdc++/91456
        * include/bits/std_function.h (__check_func_return_type): Remove.
        (function::_Callable): Use std::__is_invocable_impl instead of
        * include/std/type_traits (__is_invocable_impl): Add another defaulted
        template parameter. Define a separate partial specialization for
        INVOKE and INVOKE<void>. For INVOKE<R> replace is_convertible check
        with a check that models delayed temporary materialization.
        * testsuite/20_util/function/91456.cc: New test.
        * testsuite/20_util/is_invocable/91456.cc: New test.

Tested x86_64-linux, committed to trunk.

I might backport this to gcc-9-branch too, after some time on trunk.

patch.txt (8K) Download Attachment