13ad841b2Smrg // Implementation of INVOKE -*- C++ -*-
23ad841b2Smrg
3*4c3eb207Smrg // Copyright (C) 2016-2020 Free Software Foundation, Inc.
43ad841b2Smrg //
53ad841b2Smrg // This file is part of the GNU ISO C++ Library. This library is free
63ad841b2Smrg // software; you can redistribute it and/or modify it under the
73ad841b2Smrg // terms of the GNU General Public License as published by the
83ad841b2Smrg // Free Software Foundation; either version 3, or (at your option)
93ad841b2Smrg // any later version.
103ad841b2Smrg
113ad841b2Smrg // This library is distributed in the hope that it will be useful,
123ad841b2Smrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
133ad841b2Smrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
143ad841b2Smrg // GNU General Public License for more details.
153ad841b2Smrg
163ad841b2Smrg // Under Section 7 of GPL version 3, you are granted additional
173ad841b2Smrg // permissions described in the GCC Runtime Library Exception, version
183ad841b2Smrg // 3.1, as published by the Free Software Foundation.
193ad841b2Smrg
203ad841b2Smrg // You should have received a copy of the GNU General Public License and
213ad841b2Smrg // a copy of the GCC Runtime Library Exception along with this program;
223ad841b2Smrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
233ad841b2Smrg // <http://www.gnu.org/licenses/>.
243ad841b2Smrg
253ad841b2Smrg /** @file include/bits/invoke.h
263ad841b2Smrg * This is an internal header file, included by other library headers.
273ad841b2Smrg * Do not attempt to use it directly. @headername{functional}
283ad841b2Smrg */
293ad841b2Smrg
303ad841b2Smrg #ifndef _GLIBCXX_INVOKE_H
313ad841b2Smrg #define _GLIBCXX_INVOKE_H 1
323ad841b2Smrg
333ad841b2Smrg #pragma GCC system_header
343ad841b2Smrg
353ad841b2Smrg #if __cplusplus < 201103L
363ad841b2Smrg # include <bits/c++0x_warning.h>
373ad841b2Smrg #else
383ad841b2Smrg
393ad841b2Smrg #include <type_traits>
403ad841b2Smrg
_GLIBCXX_VISIBILITY(default)413ad841b2Smrg namespace std _GLIBCXX_VISIBILITY(default)
423ad841b2Smrg {
433ad841b2Smrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
443ad841b2Smrg
453ad841b2Smrg /**
463ad841b2Smrg * @addtogroup utilities
473ad841b2Smrg * @{
483ad841b2Smrg */
493ad841b2Smrg
503ad841b2Smrg // Used by __invoke_impl instead of std::forward<_Tp> so that a
513ad841b2Smrg // reference_wrapper is converted to an lvalue-reference.
523ad841b2Smrg template<typename _Tp, typename _Up = typename __inv_unwrap<_Tp>::type>
533ad841b2Smrg constexpr _Up&&
543ad841b2Smrg __invfwd(typename remove_reference<_Tp>::type& __t) noexcept
553ad841b2Smrg { return static_cast<_Up&&>(__t); }
563ad841b2Smrg
573ad841b2Smrg template<typename _Res, typename _Fn, typename... _Args>
583ad841b2Smrg constexpr _Res
593ad841b2Smrg __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args)
603ad841b2Smrg { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }
613ad841b2Smrg
623ad841b2Smrg template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
633ad841b2Smrg constexpr _Res
643ad841b2Smrg __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t,
653ad841b2Smrg _Args&&... __args)
663ad841b2Smrg { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); }
673ad841b2Smrg
683ad841b2Smrg template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
693ad841b2Smrg constexpr _Res
703ad841b2Smrg __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t,
713ad841b2Smrg _Args&&... __args)
723ad841b2Smrg {
733ad841b2Smrg return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...);
743ad841b2Smrg }
753ad841b2Smrg
763ad841b2Smrg template<typename _Res, typename _MemPtr, typename _Tp>
773ad841b2Smrg constexpr _Res
783ad841b2Smrg __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t)
793ad841b2Smrg { return __invfwd<_Tp>(__t).*__f; }
803ad841b2Smrg
813ad841b2Smrg template<typename _Res, typename _MemPtr, typename _Tp>
823ad841b2Smrg constexpr _Res
833ad841b2Smrg __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t)
843ad841b2Smrg { return (*std::forward<_Tp>(__t)).*__f; }
853ad841b2Smrg
863ad841b2Smrg /// Invoke a callable object.
873ad841b2Smrg template<typename _Callable, typename... _Args>
883ad841b2Smrg constexpr typename __invoke_result<_Callable, _Args...>::type
893ad841b2Smrg __invoke(_Callable&& __fn, _Args&&... __args)
903ad841b2Smrg noexcept(__is_nothrow_invocable<_Callable, _Args...>::value)
913ad841b2Smrg {
923ad841b2Smrg using __result = __invoke_result<_Callable, _Args...>;
933ad841b2Smrg using __type = typename __result::type;
943ad841b2Smrg using __tag = typename __result::__invoke_type;
953ad841b2Smrg return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
963ad841b2Smrg std::forward<_Args>(__args)...);
973ad841b2Smrg }
983ad841b2Smrg
99*4c3eb207Smrg #if __cplusplus >= 201703L
100*4c3eb207Smrg // INVOKE<R>: Invoke a callable object and convert the result to R.
101*4c3eb207Smrg template<typename _Res, typename _Callable, typename... _Args>
102*4c3eb207Smrg constexpr enable_if_t<is_invocable_r_v<_Res, _Callable, _Args...>, _Res>
103*4c3eb207Smrg __invoke_r(_Callable&& __fn, _Args&&... __args)
104*4c3eb207Smrg noexcept(is_nothrow_invocable_r_v<_Res, _Callable, _Args...>)
105*4c3eb207Smrg {
106*4c3eb207Smrg using __result = __invoke_result<_Callable, _Args...>;
107*4c3eb207Smrg using __type = typename __result::type;
108*4c3eb207Smrg using __tag = typename __result::__invoke_type;
109*4c3eb207Smrg if constexpr (is_void_v<_Res>)
110*4c3eb207Smrg std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
111*4c3eb207Smrg std::forward<_Args>(__args)...);
112*4c3eb207Smrg else
113*4c3eb207Smrg return std::__invoke_impl<__type>(__tag{},
114*4c3eb207Smrg std::forward<_Callable>(__fn),
115*4c3eb207Smrg std::forward<_Args>(__args)...);
116*4c3eb207Smrg }
117*4c3eb207Smrg #else // C++11
118*4c3eb207Smrg template<typename _Res, typename _Callable, typename... _Args>
119*4c3eb207Smrg using __can_invoke_as_void = __enable_if_t<
120*4c3eb207Smrg __and_<is_void<_Res>, __is_invocable<_Callable, _Args...>>::value,
121*4c3eb207Smrg _Res
122*4c3eb207Smrg >;
123*4c3eb207Smrg
124*4c3eb207Smrg template<typename _Res, typename _Callable, typename... _Args>
125*4c3eb207Smrg using __can_invoke_as_nonvoid = __enable_if_t<
126*4c3eb207Smrg __and_<__not_<is_void<_Res>>,
127*4c3eb207Smrg is_convertible<typename __invoke_result<_Callable, _Args...>::type,
128*4c3eb207Smrg _Res>
129*4c3eb207Smrg >::value,
130*4c3eb207Smrg _Res
131*4c3eb207Smrg >;
132*4c3eb207Smrg
133*4c3eb207Smrg // INVOKE<R>: Invoke a callable object and convert the result to R.
134*4c3eb207Smrg template<typename _Res, typename _Callable, typename... _Args>
135*4c3eb207Smrg constexpr __can_invoke_as_nonvoid<_Res, _Callable, _Args...>
136*4c3eb207Smrg __invoke_r(_Callable&& __fn, _Args&&... __args)
137*4c3eb207Smrg {
138*4c3eb207Smrg using __result = __invoke_result<_Callable, _Args...>;
139*4c3eb207Smrg using __type = typename __result::type;
140*4c3eb207Smrg using __tag = typename __result::__invoke_type;
141*4c3eb207Smrg return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
142*4c3eb207Smrg std::forward<_Args>(__args)...);
143*4c3eb207Smrg }
144*4c3eb207Smrg
145*4c3eb207Smrg // INVOKE<R> when R is cv void
146*4c3eb207Smrg template<typename _Res, typename _Callable, typename... _Args>
147*4c3eb207Smrg _GLIBCXX14_CONSTEXPR __can_invoke_as_void<_Res, _Callable, _Args...>
148*4c3eb207Smrg __invoke_r(_Callable&& __fn, _Args&&... __args)
149*4c3eb207Smrg {
150*4c3eb207Smrg using __result = __invoke_result<_Callable, _Args...>;
151*4c3eb207Smrg using __type = typename __result::type;
152*4c3eb207Smrg using __tag = typename __result::__invoke_type;
153*4c3eb207Smrg std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
154*4c3eb207Smrg std::forward<_Args>(__args)...);
155*4c3eb207Smrg }
156*4c3eb207Smrg #endif // C++11
157*4c3eb207Smrg
1583ad841b2Smrg _GLIBCXX_END_NAMESPACE_VERSION
1593ad841b2Smrg } // namespace std
1603ad841b2Smrg
1613ad841b2Smrg #endif // C++11
1623ad841b2Smrg
1633ad841b2Smrg #endif // _GLIBCXX_INVOKE_H
164