[PATCH] Define std::__invoke_r for INVOKE<R>
Jonathan Wakely
jwakely@redhat.com
Fri May 17 09:15:00 GMT 2019
On 17/05/19 10:49 +0200, Stephan Bergmann wrote:
>On 14/05/2019 17:25, Jonathan Wakely wrote:
>> Â Â Â Â * include/bits/invoke.h (__invoke_r): Define new function implementing
>> Â Â Â Â the INVOKE<R> pseudo-function.
>> Â Â Â Â * testsuite/20_util/function_objects/invoke/1.cc: Add more tests.
>> Â Â Â Â * testsuite/20_util/function_objects/invoke/2.cc: New test.
>>
>>Tested powerpc64le-linux, committed to trunk.
>
>>diff --git a/libstdc++-v3/include/bits/invoke.h b/libstdc++-v3/include/bits/invoke.h
>>index a5278a59f0c..59e22da84d4 100644
>>--- a/libstdc++-v3/include/bits/invoke.h
>>+++ b/libstdc++-v3/include/bits/invoke.h
>>@@ -96,6 +96,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> std::forward<_Args>(__args)...);
>> }
>>+#if __cplusplus >= 201703L
>>+ // INVOKE<R>: Invoke a callable object and convert the result to R.
>>+ template<typename _Res, typename _Callable, typename... _Args>
>>+ constexpr enable_if_t<is_invocable_r_v<_Res, _Callable, _Args...>, _Res>
>>+ __invoke_r(_Callable&& __fn, _Args&&... __args)
>>+ noexcept(is_nothrow_invocable_r_v<_Res, _Callable, _Args...>)
>>+ {
>>+ using __result = __invoke_result<_Callable, _Args...>;
>>+ using __type = typename __result::type;
>>+ using __tag = typename __result::__invoke_type;
>>+ if constexpr (is_void_v<_Res>)
>>+ std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
>>+ std::forward<_Args>(__args)...);
>>+ else
>>+ return std::__invoke_impl<__type>(__tag{},
>>+ std::forward<_Callable>(__fn),
>>+ std::forward<_Args>(__args)...);
>>+ }
>>+#else // C++11
>>+ template<typename _Res, typename _Callable, typename... _Args>
>>+ using __can_invoke_as_void = __enable_if_t<
>>+ __and_<is_void<_Res>, __is_invocable<_Callable, _Args...>>::value,
>>+ _Res
>>+ >;
>>+
>>+ template<typename _Res, typename _Callable, typename... _Args>
>>+ using __can_invoke_as_nonvoid = __enable_if_t<
>>+ __and_<__not_<is_void<_Res>>,
>>+ is_convertible<typename __invoke_result<_Callable, _Args...>::type,
>>+ _Res>
>>+ >::value,
>>+ _Res
>>+ >;
>>+
>>+ // INVOKE<R>: Invoke a callable object and convert the result to R.
>>+ template<typename _Res, typename _Callable, typename... _Args>
>>+ constexpr __can_invoke_as_nonvoid<_Res, _Callable, _Args...>
>>+ __invoke_r(_Callable&& __fn, _Args&&... __args)
>>+ {
>>+ using __result = __invoke_result<_Callable, _Args...>;
>>+ using __type = typename __result::type;
>>+ using __tag = typename __result::__invoke_type;
>>+ return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
>>+ std::forward<_Args>(__args)...);
>>+ }
>>+
>>+ // INVOKE<R> when R is cv void
>>+ template<typename _Res, typename _Callable, typename... _Args>
>>+ constexpr __can_invoke_as_void<_Res, _Callable, _Args...>
>>+ __invoke_r(_Callable&& __fn, _Args&&... __args)
>
>I think this is a problem with -std=c++11 (but not -std=c++14) where
>void is not yet a literal type, so this function can't be constexpr?
Yes, Clang diagnoses this in C++11 mode but G++ accepts it (unless you
actually try to call g<T>() in a constant expression):
template<typename T> struct voidy { using type = void; };
template<typename T> constexpr typename voidy<T>::type g() {}
$ clang++ v.cc -std=c++11
v.cc:2:56: error: no return statement in constexpr function
template<typename T> constexpr typename voidy<T>::type g() {}
^
1 error generated.
I'm testing the attached fix. Thanks for the report.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.txt
Type: text/x-patch
Size: 986 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20190517/ee6d6b19/attachment.bin>
More information about the Libstdc++
mailing list