xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/bits/invoke.h (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
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