1  // Implementation of INVOKE -*- C++ -*-
       2  
       3  // Copyright (C) 2016-2023 Free Software Foundation, Inc.
       4  //
       5  // This file is part of the GNU ISO C++ Library.  This library is free
       6  // software; you can redistribute it and/or modify it under the
       7  // terms of the GNU General Public License as published by the
       8  // Free Software Foundation; either version 3, or (at your option)
       9  // any later version.
      10  
      11  // This library is distributed in the hope that it will be useful,
      12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  // GNU General Public License for more details.
      15  
      16  // Under Section 7 of GPL version 3, you are granted additional
      17  // permissions described in the GCC Runtime Library Exception, version
      18  // 3.1, as published by the Free Software Foundation.
      19  
      20  // You should have received a copy of the GNU General Public License and
      21  // a copy of the GCC Runtime Library Exception along with this program;
      22  // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23  // <http://www.gnu.org/licenses/>.
      24  
      25  /** @file include/bits/invoke.h
      26   *  This is an internal header file, included by other library headers.
      27   *  Do not attempt to use it directly. @headername{functional}
      28   */
      29  
      30  #ifndef _GLIBCXX_INVOKE_H
      31  #define _GLIBCXX_INVOKE_H 1
      32  
      33  #pragma GCC system_header
      34  
      35  #if __cplusplus < 201103L
      36  # include <bits/c++0x_warning.h>
      37  #else
      38  
      39  #include <type_traits>
      40  #include <bits/move.h> // forward
      41  
      42  namespace std _GLIBCXX_VISIBILITY(default)
      43  {
      44  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      45  
      46    /**
      47     *  @addtogroup utilities
      48     *  @{
      49     */
      50  
      51    // Used by __invoke_impl instead of std::forward<_Tp> so that a
      52    // reference_wrapper is converted to an lvalue-reference.
      53    template<typename _Tp, typename _Up = typename __inv_unwrap<_Tp>::type>
      54      constexpr _Up&&
      55      __invfwd(typename remove_reference<_Tp>::type& __t) noexcept
      56      { return static_cast<_Up&&>(__t); }
      57  
      58    template<typename _Res, typename _Fn, typename... _Args>
      59      constexpr _Res
      60      __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args)
      61      { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }
      62  
      63    template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
      64      constexpr _Res
      65      __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t,
      66  		  _Args&&... __args)
      67      { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); }
      68  
      69    template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
      70      constexpr _Res
      71      __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t,
      72  		  _Args&&... __args)
      73      {
      74        return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...);
      75      }
      76  
      77    template<typename _Res, typename _MemPtr, typename _Tp>
      78      constexpr _Res
      79      __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t)
      80      { return __invfwd<_Tp>(__t).*__f; }
      81  
      82    template<typename _Res, typename _MemPtr, typename _Tp>
      83      constexpr _Res
      84      __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t)
      85      { return (*std::forward<_Tp>(__t)).*__f; }
      86  
      87    /// Invoke a callable object.
      88    template<typename _Callable, typename... _Args>
      89      constexpr typename __invoke_result<_Callable, _Args...>::type
      90      __invoke(_Callable&& __fn, _Args&&... __args)
      91      noexcept(__is_nothrow_invocable<_Callable, _Args...>::value)
      92      {
      93        using __result = __invoke_result<_Callable, _Args...>;
      94        using __type = typename __result::type;
      95        using __tag = typename __result::__invoke_type;
      96        return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
      97  					std::forward<_Args>(__args)...);
      98      }
      99  
     100  #if __cplusplus >= 201703L
     101    // INVOKE<R>: Invoke a callable object and convert the result to R.
     102    template<typename _Res, typename _Callable, typename... _Args>
     103      constexpr enable_if_t<is_invocable_r_v<_Res, _Callable, _Args...>, _Res>
     104      __invoke_r(_Callable&& __fn, _Args&&... __args)
     105      noexcept(is_nothrow_invocable_r_v<_Res, _Callable, _Args...>)
     106      {
     107        using __result = __invoke_result<_Callable, _Args...>;
     108        using __type = typename __result::type;
     109        using __tag = typename __result::__invoke_type;
     110        if constexpr (is_void_v<_Res>)
     111  	std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
     112  					std::forward<_Args>(__args)...);
     113        else
     114  	return std::__invoke_impl<__type>(__tag{},
     115  					  std::forward<_Callable>(__fn),
     116  					  std::forward<_Args>(__args)...);
     117      }
     118  #else // C++11 or C++14
     119    // This is a non-SFINAE-friendly std::invoke_r<R>(fn, args...) for C++11/14.
     120    // It's used in std::function, std::bind, and std::packaged_task. Only
     121    // std::function is constrained on is_invocable_r, but that is checked on
     122    // construction so doesn't need to be checked again when calling __invoke_r.
     123    // Consequently, these __invoke_r overloads do not check for invocable
     124    // arguments, nor check that the invoke result is convertible to R.
     125  
     126    // INVOKE<R>: Invoke a callable object and convert the result to R.
     127    template<typename _Res, typename _Callable, typename... _Args>
     128      constexpr __enable_if_t<!is_void<_Res>::value, _Res>
     129      __invoke_r(_Callable&& __fn, _Args&&... __args)
     130      {
     131        using __result = __invoke_result<_Callable, _Args...>;
     132        using __type = typename __result::type;
     133  #if __has_builtin(__reference_converts_from_temporary)
     134        static_assert(!__reference_converts_from_temporary(_Res, __type),
     135  		    "INVOKE<R> must not create a dangling reference");
     136  #endif
     137        using __tag = typename __result::__invoke_type;
     138        return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
     139  					std::forward<_Args>(__args)...);
     140      }
     141  
     142    // INVOKE<R> when R is cv void
     143    template<typename _Res, typename _Callable, typename... _Args>
     144      _GLIBCXX14_CONSTEXPR __enable_if_t<is_void<_Res>::value, _Res>
     145      __invoke_r(_Callable&& __fn, _Args&&... __args)
     146      {
     147        using __result = __invoke_result<_Callable, _Args...>;
     148        using __type = typename __result::type;
     149        using __tag = typename __result::__invoke_type;
     150        std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
     151  				 std::forward<_Args>(__args)...);
     152      }
     153  #endif // C++11 or C++14
     154  
     155  _GLIBCXX_END_NAMESPACE_VERSION
     156  } // namespace std
     157  
     158  #endif // C++11
     159  
     160  #endif // _GLIBCXX_INVOKE_H