On 15/08/19 17:04 +0100, Jonathan Wakely wrote: >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. >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 > __check_func_return_type. > * include/std/type_traits (__is_invocable_impl): Add another defaulted > template parameter. Define a separate partial specialization for > INVOKE and INVOKE. For INVOKE 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. With some minor changes to __is_convertible_helper we could make that usable by both std::is_convertible and __is_invokable_impl. I don't plan to commit this now but might do at a later date.