// Implementation of std::move_only_function -*- C++ -*-

// Copyright The GNU Toolchain Authors.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file include/bits/mofunc_impl.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{functional}
 */

#ifndef _GLIBCXX_MOF_CV
# define _GLIBCXX_MOF_CV
#endif

#ifdef _GLIBCXX_MOF_REF
# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
#else
# define _GLIBCXX_MOF_REF
# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV &
#endif

#define _GLIBCXX_MOF_CV_REF _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   *  @brief Polymorphic function wrapper.
   *  @ingroup functors
   *  @since C++23
   *  @headerfile functional
   *
   *  The `std::move_only_function` class template is a call wrapper similar
   *  to `std::function`, but does not require the stored target function
   *  to be copyable.
   *
   *  It also supports const-qualification, ref-qualification, and
   *  no-throw guarantees. The qualifications and exception-specification
   *  of the `move_only_function::operator()` member function are respected
   *  when invoking the target function.
   */
  template<typename _Res, typename... _ArgTypes, bool _Noex>
    class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
			       _GLIBCXX_MOF_REF noexcept(_Noex)>
    : _Mofunc_base
    {
      template<typename _Tp>
	using __callable
	  = __conditional_t<_Noex,
			    is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>,
			    is_invocable_r<_Res, _Tp, _ArgTypes...>>;

      // [func.wrap.mov.con]/1 is-callable-from<VT>
      template<typename _Vt>
	static constexpr bool __is_callable_from
	  = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>,
		    __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>;

    public:
      using result_type = _Res;

      /// Creates an empty object.
      move_only_function() noexcept { }

      /// Creates an empty object.
      move_only_function(nullptr_t) noexcept { }

      /// Moves the target object, leaving the source empty.
      move_only_function(move_only_function&& __x) noexcept
      : _Mofunc_base(static_cast<_Mofunc_base&&>(__x)),
	_M_invoke(std::__exchange(__x._M_invoke, nullptr))
      { }

      /// Stores a target object initialized from the argument.
      template<typename _Fn, typename _Vt = decay_t<_Fn>>
	requires (!is_same_v<_Vt, move_only_function>)
	  && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
	move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
	{
	  if constexpr (is_function_v<remove_pointer_t<_Vt>>
			|| is_member_pointer_v<_Vt>
			|| __is_move_only_function_v<_Vt>)
	    {
	      if (__f == nullptr)
		return;
	    }
	  _M_init<_Vt>(std::forward<_Fn>(__f));
	  _M_invoke = &_S_invoke<_Vt>;
	}

      /// Stores a target object initialized from the arguments.
      template<typename _Tp, typename... _Args>
	requires is_constructible_v<_Tp, _Args...>
	  && __is_callable_from<_Tp>
	explicit
	move_only_function(in_place_type_t<_Tp>, _Args&&... __args)
	noexcept(_S_nothrow_init<_Tp, _Args...>())
	: _M_invoke(&_S_invoke<_Tp>)
	{
	  static_assert(is_same_v<decay_t<_Tp>, _Tp>);
	  _M_init<_Tp>(std::forward<_Args>(__args)...);
	}

      /// Stores a target object initialized from the arguments.
      template<typename _Tp, typename _Up, typename... _Args>
	requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
	  && __is_callable_from<_Tp>
	explicit
	move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
			   _Args&&... __args)
	noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
	: _M_invoke(&_S_invoke<_Tp>)
	{
	  static_assert(is_same_v<decay_t<_Tp>, _Tp>);
	  _M_init<_Tp>(__il, std::forward<_Args>(__args)...);
	}

      /// Stores a new target object, leaving `x` empty.
      move_only_function&
      operator=(move_only_function&& __x) noexcept
      {
	_Mofunc_base::operator=(static_cast<_Mofunc_base&&>(__x));
	_M_invoke = std::__exchange(__x._M_invoke, nullptr);
	return *this;
      }

      /// Destroys the target object (if any).
      move_only_function&
      operator=(nullptr_t) noexcept
      {
	_Mofunc_base::operator=(nullptr);
	_M_invoke = nullptr;
	return *this;
      }

      /// Stores a new target object, initialized from the argument.
      template<typename _Fn>
	requires is_constructible_v<move_only_function, _Fn>
	move_only_function&
	operator=(_Fn&& __f)
	noexcept(is_nothrow_constructible_v<move_only_function, _Fn>)
	{
	  move_only_function(std::forward<_Fn>(__f)).swap(*this);
	  return *this;
	}

      ~move_only_function() = default;

      /// True if a target object is present, false otherwise.
      explicit operator bool() const noexcept { return _M_invoke != nullptr; }

      /** Invoke the target object.
       *
       * The target object will be invoked using the supplied arguments,
       * and as an lvalue or rvalue, and as const or non-const, as dictated
       * by the template arguments of the `move_only_function` specialization.
       *
       * @pre Must not be empty.
       */
      _Res
      operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
      {
	__glibcxx_assert(*this != nullptr);
	return _M_invoke(this, std::forward<_ArgTypes>(__args)...);
      }

      /// Exchange the target objects (if any).
      void
      swap(move_only_function& __x) noexcept
      {
	_Mofunc_base::swap(__x);
	std::swap(_M_invoke, __x._M_invoke);
      }

      /// Exchange the target objects (if any).
      friend void
      swap(move_only_function& __x, move_only_function& __y) noexcept
      { __x.swap(__y); }

      /// Check for emptiness by comparing with `nullptr`.
      friend bool
      operator==(const move_only_function& __x, nullptr_t) noexcept
      { return __x._M_invoke == nullptr; }

    private:
      template<typename _Tp>
	using __param_t = __conditional_t<is_scalar_v<_Tp>, _Tp, _Tp&&>;

      using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*,
				__param_t<_ArgTypes>...) noexcept(_Noex);

      template<typename _Tp>
	static _Res
	_S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self,
		  __param_t<_ArgTypes>... __args) noexcept(_Noex)
	{
	  using _TpCv = _Tp _GLIBCXX_MOF_CV;
	  using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS;
	  return std::__invoke_r<_Res>(
	      std::forward<_TpInv>(*_S_access<_TpCv>(__self)),
	      std::forward<__param_t<_ArgTypes>>(__args)...);
	}

      _Invoker _M_invoke = nullptr;
    };

#undef _GLIBCXX_MOF_CV_REF
#undef _GLIBCXX_MOF_CV
#undef _GLIBCXX_MOF_REF
#undef _GLIBCXX_MOF_INV_QUALS

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
