chromium/third_party/libc++/src/include/__functional/function.h

// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___FUNCTIONAL_FUNCTION_H
#define _LIBCPP___FUNCTIONAL_FUNCTION_H

#include <__assert>
#include <__config>
#include <__exception/exception.h>
#include <__functional/binary_function.h>
#include <__functional/invoke.h>
#include <__functional/unary_function.h>
#include <__iterator/iterator_traits.h>
#include <__memory/addressof.h>
#include <__memory/allocator.h>
#include <__memory/allocator_destructor.h>
#include <__memory/allocator_traits.h>
#include <__memory/builtin_new_allocator.h>
#include <__memory/compressed_pair.h>
#include <__memory/unique_ptr.h>
#include <__type_traits/aligned_storage.h>
#include <__type_traits/decay.h>
#include <__type_traits/is_core_convertible.h>
#include <__type_traits/is_scalar.h>
#include <__type_traits/is_trivially_constructible.h>
#include <__type_traits/is_trivially_destructible.h>
#include <__type_traits/is_void.h>
#include <__type_traits/strip_signature.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#include <__utility/piecewise_construct.h>
#include <__utility/swap.h>
#include <__verbose_abort>
#include <new>
#include <tuple>
#include <typeinfo>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#  pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

#ifndef _LIBCPP_CXX03_LANG

_LIBCPP_BEGIN_NAMESPACE_STD

// bad_function_call

_LIBCPP_DIAGNOSTIC_PUSH
#  if !_LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_KEY_FUNCTION
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables")
#  endif
class _LIBCPP_EXPORTED_FROM_ABI bad_function_call : public exception {};
_LIBCPP_DIAGNOSTIC_POP

_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_function_call() {}

template <class _Fp>
class _LIBCPP_TEMPLATE_VIS function; // undefined

namespace __function {

template <class _Rp>
struct __maybe_derive_from_unary_function {};

__maybe_derive_from_unary_function<_Rp (_A1)>;

template <class _Rp>
struct __maybe_derive_from_binary_function {};

__maybe_derive_from_binary_function<_Rp (_A1, _A2)>;

template <class _Fp>
_LIBCPP_HIDE_FROM_ABI bool __not_null(_Fp const&) {}

template <class _Fp>
_LIBCPP_HIDE_FROM_ABI bool __not_null(_Fp* __ptr) {}

template <class _Ret, class _Class>
_LIBCPP_HIDE_FROM_ABI bool __not_null(_Ret _Class::*__ptr) {}

template <class _Fp>
_LIBCPP_HIDE_FROM_ABI bool __not_null(function<_Fp> const& __f) {}

#  ifdef _LIBCPP_HAS_EXTENSION_BLOCKS
template <class _Rp, class... _Args>
_LIBCPP_HIDE_FROM_ABI bool __not_null(_Rp (^__p)(_Args...)) {
  return __p;
}
#  endif

} // namespace __function

namespace __function {

// __alloc_func holds a functor and an allocator.

template <class _Fp, class _Ap, class _FB>
class __alloc_func;
template <class _Fp, class _FB>
class __default_alloc_func;

__alloc_func<_Fp, _Ap, _Rp (_ArgTypes...)>;

__default_alloc_func<_Fp, _Rp (_ArgTypes...)>;

// __base provides an abstract interface for copyable functors.

template <class _Fp>
class _LIBCPP_TEMPLATE_VIS __base;

__base<_Rp (_ArgTypes...)>;

// __func implements __base for a given functor type.

template <class _FD, class _Alloc, class _FB>
class __func;

__func<_Fp, _Alloc, _Rp (_ArgTypes...)>;

template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
__base<_Rp(_ArgTypes...)>* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone() const {}

template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const {}

template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPT {}

template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() _NOEXCEPT {}

template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
_Rp __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&&... __arg) {}

#  ifndef _LIBCPP_HAS_NO_RTTI

template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
const void* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT {
  if (__ti == typeid(_Fp))
    return std::addressof(__f_.__target());
  return nullptr;
}

template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
const std::type_info& __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT {
  return typeid(_Fp);
}

#  endif // _LIBCPP_HAS_NO_RTTI

// __value_func creates a value-type from a __func.

template <class _Fp>
class __value_func;

__value_func<_Rp (_ArgTypes...)>;

// Storage for a functor object, to be used with __policy to manage copy and
// destruction.
__policy_storage;

// True if _Fun can safely be held in __policy_storage.__small.
template <typename _Fun>
struct __use_small_storage
    : public integral_constant<
          bool,
          sizeof(_Fun) <= sizeof(__policy_storage)&& _LIBCPP_ALIGNOF(_Fun) <= _LIBCPP_ALIGNOF(__policy_storage) &&
              is_trivially_copy_constructible<_Fun>::value && is_trivially_destructible<_Fun>::value> {};

// Policy contains information about how to copy, destroy, and move the
// underlying functor. You can think of it as a vtable of sorts.
struct __policy {};

// Used to choose between perfect forwarding or pass-by-value. Pass-by-value is
// faster for types that can be passed in registers.
__fast_forward;

// __policy_invoker calls an instance of __alloc_func held in __policy_storage.

template <class _Fp>
struct __policy_invoker;

__policy_invoker<_Rp (_ArgTypes...)>;

// __policy_func uses a __policy and __policy_invoker to create a type-erased,
// copyable functor.

template <class _Fp>
class __policy_func;

__policy_func<_Rp (_ArgTypes...)>;

#  if defined(_LIBCPP_HAS_BLOCKS_RUNTIME)

extern "C" void* _Block_copy(const void*);
extern "C" void _Block_release(const void*);

template <class _Rp1, class... _ArgTypes1, class _Alloc, class _Rp, class... _ArgTypes>
class __func<_Rp1 (^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> {
  typedef _Rp1 (^__block_type)(_ArgTypes1...);
  __block_type __f_;

public:
  _LIBCPP_HIDE_FROM_ABI explicit __func(__block_type const& __f)
#    ifdef _LIBCPP_HAS_OBJC_ARC
      : __f_(__f)
#    else
      : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr))
#    endif
  {
  }

  // [TODO] add && to save on a retain

  _LIBCPP_HIDE_FROM_ABI explicit __func(__block_type __f, const _Alloc& /* unused */)
#    ifdef _LIBCPP_HAS_OBJC_ARC
      : __f_(__f)
#    else
      : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr))
#    endif
  {
  }

  _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual __base<_Rp(_ArgTypes...)>* __clone() const {
    _LIBCPP_ASSERT_INTERNAL(
        false,
        "Block pointers are just pointers, so they should always fit into "
        "std::function's small buffer optimization. This function should "
        "never be invoked.");
    return nullptr;
  }

  _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __clone(__base<_Rp(_ArgTypes...)>* __p) const {
    ::new ((void*)__p) __func(__f_);
  }

  _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy() _NOEXCEPT {
#    ifndef _LIBCPP_HAS_OBJC_ARC
    if (__f_)
      _Block_release(__f_);
#    endif
    __f_ = 0;
  }

  _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate() _NOEXCEPT {
    _LIBCPP_ASSERT_INTERNAL(
        false,
        "Block pointers are just pointers, so they should always fit into "
        "std::function's small buffer optimization. This function should "
        "never be invoked.");
  }

  _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual _Rp operator()(_ArgTypes&&... __arg) {
    return std::__invoke(__f_, std::forward<_ArgTypes>(__arg)...);
  }

#    ifndef _LIBCPP_HAS_NO_RTTI
  _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const void* target(type_info const& __ti) const _NOEXCEPT {
    if (__ti == typeid(__func::__block_type))
      return &__f_;
    return (const void*)nullptr;
  }

  _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const std::type_info& target_type() const _NOEXCEPT {
    return typeid(__func::__block_type);
  }
#    endif // _LIBCPP_HAS_NO_RTTI
};

#  endif // _LIBCPP_HAS_EXTENSION_BLOCKS

} // namespace __function

function<_Rp (_ArgTypes...)>;

#  if _LIBCPP_STD_VER >= 17
template <class _Rp, class... _Ap>
function(_Rp (*)(_Ap...)) -> function<_Rp(_Ap...)>;

template <class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type>
function(_Fp) -> function<_Stripped>;
#  endif // _LIBCPP_STD_VER >= 17

template <class _Rp, class... _ArgTypes>
function<_Rp(_ArgTypes...)>::function(const function& __f) :{}

#  if _LIBCPP_STD_VER <= 14
template <class _Rp, class... _ArgTypes>
template <class _Alloc>
function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, const function& __f) : __f_(__f.__f_) {}
#  endif

template <class _Rp, class... _ArgTypes>
function<_Rp(_ArgTypes...)>::function(function&& __f) _NOEXCEPT :{}

#  if _LIBCPP_STD_VER <= 14
template <class _Rp, class... _ArgTypes>
template <class _Alloc>
function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, function&& __f) : __f_(std::move(__f.__f_)) {}
#  endif

template <class _Rp, class... _ArgTypes>
template <class _Fp, class>
function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(std::move(__f)) {}

#  if _LIBCPP_STD_VER <= 14
template <class _Rp, class... _ArgTypes>
template <class _Fp, class _Alloc, class>
function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a, _Fp __f) : __f_(std::move(__f), __a) {}
#  endif

template <class _Rp, class... _ArgTypes>
function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(const function& __f) {}

template <class _Rp, class... _ArgTypes>
function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPT {}

template <class _Rp, class... _ArgTypes>
function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPT {}

template <class _Rp, class... _ArgTypes>
template <class _Fp, class>
function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f) {}

template <class _Rp, class... _ArgTypes>
function<_Rp(_ArgTypes...)>::~function() {}

template <class _Rp, class... _ArgTypes>
void function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPT {}

template <class _Rp, class... _ArgTypes>
_Rp function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const {}

#  ifndef _LIBCPP_HAS_NO_RTTI

template <class _Rp, class... _ArgTypes>
const std::type_info& function<_Rp(_ArgTypes...)>::target_type() const _NOEXCEPT {
  return __f_.target_type();
}

template <class _Rp, class... _ArgTypes>
template <typename _Tp>
_Tp* function<_Rp(_ArgTypes...)>::target() _NOEXCEPT {
  return (_Tp*)(__f_.template target<_Tp>());
}

template <class _Rp, class... _ArgTypes>
template <typename _Tp>
const _Tp* function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT {
  return __f_.template target<_Tp>();
}

#  endif // _LIBCPP_HAS_NO_RTTI

template <class _Rp, class... _ArgTypes>
inline _LIBCPP_HIDE_FROM_ABI bool operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {}

#  if _LIBCPP_STD_VER <= 17

template <class _Rp, class... _ArgTypes>
inline _LIBCPP_HIDE_FROM_ABI bool operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {
  return !__f;
}

template <class _Rp, class... _ArgTypes>
inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {
  return (bool)__f;
}

template <class _Rp, class... _ArgTypes>
inline _LIBCPP_HIDE_FROM_ABI bool operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {
  return (bool)__f;
}

#  endif // _LIBCPP_STD_VER <= 17

template <class _Rp, class... _ArgTypes>
inline _LIBCPP_HIDE_FROM_ABI void swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) _NOEXCEPT {}

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP_CXX03_LANG

_LIBCPP_POP_MACROS

#endif // _LIBCPP___FUNCTIONAL_FUNCTION_H