#pragma once
#ifdef ARDUINO_ARCH_AVR
/*	Copyright (C) 2004 Garrett A. Kajmowicz
	This file is part of the uClibc++ Library.
	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, 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
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#include <typeinfo>
#include <bits/invoke.h>
#define __glibcxx_want_invoke
#include <bits/version.h>
#pragma GCC visibility push(default)

namespace std
{

	template <class Arg, class Result>
	struct unary_function;
	template <class Arg1, class Arg2, class Result>
	struct binary_function;

	template <class T>
	struct plus;
	template <class T>
	struct minus;
	template <class T>
	struct multiplies;
	template <class T>
	struct divides;
	template <class T>
	struct modulus;
	template <class T>
	struct negate;

	template <class T>
	struct equal_to;
	template <class T>
	struct not_equal_to;
	template <class T>
	struct greater;
	template <class T>
	struct less;
	template <class T>
	struct greater_equal;
	template <class T>
	struct less_equal;

	template <class T>
	struct logical_and;
	template <class T>
	struct logical_or;
	template <class T>
	struct logical_not;

	template <class Predicate>
	struct unary_negate;
	template <class Predicate>
	unary_negate<Predicate> not1(const Predicate &);
	template <class Predicate>
	struct binary_negate;
	template <class Predicate>
	binary_negate<Predicate> not2(const Predicate &);

	template <class Operation>
	class binder1st;
	template <class Operation, class T>
	binder1st<Operation> bind1st(const Operation &, const T &);
	template <class Operation>
	class binder2nd;
	template <class Operation, class T>
	binder2nd<Operation> bind2nd(const Operation &, const T &);

	template <class Arg, class Result>
	class pointer_to_unary_function;
	template <class Arg, class Result>
	pointer_to_unary_function<Arg, Result> ptr_fun(Result (*)(Arg));
	template <class Arg1, class Arg2, class Result>
	class pointer_to_binary_function;
	template <class Arg1, class Arg2, class Result>
	pointer_to_binary_function<Arg1, Arg2, Result> ptr_fun(Result (*)(Arg1, Arg2));

	template <class S, class T>
	class mem_fun_t;
	template <class S, class T, class A>
	class mem_fun1_t;
	template <class S, class T>
	class const_mem_fun_t;
	template <class S, class T, class A>
	class const_mem_fun1_t;
	template <class S, class T>
	mem_fun_t<S, T> mem_fun(S (T::*f)());
	template <class S, class T, class A>
	mem_fun1_t<S, T, A> mem_fun(S (T::*f)(A));
	template <class S, class T>
	class mem_fun_ref_t;
	template <class S, class T, class A>
	class mem_fun1_ref_t;
	template <class S, class T>
	mem_fun_ref_t<S, T> mem_fun_ref(S (T::*f)());
	template <class S, class T, class A>
	mem_fun1_ref_t<S, T, A> mem_fun1_ref(S (T::*f)(A));

	template <class T>
	struct _UCXXEXPORT plus : binary_function<T, T, T>
	{
		T operator()(const T &x, const T &y) const
		{
			return x + y;
		}
	};

	template <class T>
	struct _UCXXEXPORT minus : binary_function<T, T, T>
	{
		T operator()(const T &x, const T &y) const
		{
			return x - y;
		}
	};

	template <class T>
	struct _UCXXEXPORT multiplies : binary_function<T, T, T>
	{
		T operator()(const T &x, const T &y) const
		{
			return x * y;
		}
	};

	template <class T>
	struct _UCXXEXPORT divides : binary_function<T, T, T>
	{
		T operator()(const T &x, const T &y) const
		{
			return x / y;
		}
	};

	template <class T>
	struct _UCXXEXPORT modulus : binary_function<T, T, T>
	{
		T operator()(const T &x, const T &y) const
		{
			return x % y;
		}
	};

	template <class T>
	struct _UCXXEXPORT negate : unary_function<T, T>
	{
		T operator()(const T &x) const
		{
			return -x;
		}
	};

	template <class T>
	struct _UCXXEXPORT equal_to : binary_function<T, T, bool>
	{
		bool operator()(const T &x, const T &y) const
		{
			return (x == y);
		}
	};

	template <class T>
	struct _UCXXEXPORT not_equal_to : binary_function<T, T, bool>
	{
		bool operator()(const T &x, const T &y) const
		{
			return (x != y);
		}
	};

	template <class T>
	struct _UCXXEXPORT greater : binary_function<T, T, bool>
	{
		bool operator()(const T &x, const T &y) const _UCXX_NOTHROW
		{
			return (x > y);
		}
	};

	template <class T>
	struct _UCXXEXPORT less : binary_function<T, T, bool>
	{
		bool operator()(const T &x, const T &y) const _UCXX_NOTHROW
		{
			return (x < y);
		}
	};

	template <class T>
	struct _UCXXEXPORT greater_equal : binary_function<T, T, bool>
	{
		bool operator()(const T &x, const T &y) const _UCXX_NOTHROW
		{
			return (x >= y);
		}
	};

	template <class T>
	struct _UCXXEXPORT less_equal : binary_function<T, T, bool>
	{
		bool operator()(const T &x, const T &y) const _UCXX_NOTHROW
		{
			return (x <= y);
		}
	};

	template <class T>
	struct _UCXXEXPORT logical_and : binary_function<T, T, bool>
	{
		bool operator()(const T &x, const T &y) const
		{
			return (x && y);
		}
	};

	template <class T>
	struct _UCXXEXPORT logical_or : binary_function<T, T, bool>
	{
		bool operator()(const T &x, const T &y) const
		{
			return (x || y);
		}
	};

	template <class T>
	struct _UCXXEXPORT logical_not : unary_function<T, bool>
	{
		bool operator()(const T &x) const
		{
			return !x;
		}
	};

	template <class Predicate>
	class _UCXXEXPORT unary_negate
		: public unary_function<typename Predicate::argument_type, bool>
	{
	public:
		explicit unary_negate(const Predicate &pred) : p(pred) {}
		bool operator()(const typename Predicate::argument_type &x) const
		{
			return !p(x);
		}

	private:
		Predicate p;
	};

	template <class Predicate>
	_UCXXEXPORT unary_negate<Predicate> not1(const Predicate &pred)
	{
		return unary_negate<Predicate>(pred);
	}

	template <class Predicate>
	class _UCXXEXPORT binary_negate : public binary_function<typename Predicate::first_argument_type,
															 typename Predicate::second_argument_type, bool>
	{
	public:
		explicit binary_negate(const Predicate &pred) : p(pred) {}
		bool operator()(const typename Predicate::first_argument_type &x,
						const typename Predicate::second_argument_type &y) const
		{
			return !p(x, y);
		}

	private:
		Predicate p;
	};

	template <class Predicate>
	_UCXXEXPORT binary_negate<Predicate> not2(const Predicate &pred)
	{
		return binary_negate<Predicate>(pred);
	}

	template <class Operation>
	class _UCXXEXPORT binder1st
		: public unary_function<typename Operation::second_argument_type,
								typename Operation::result_type>
	{
	protected:
		Operation op;
		typename Operation::first_argument_type value;

	public:
		binder1st(const Operation &x, const typename Operation::first_argument_type &y) : op(x), value(y) {}
		typename Operation::result_type operator()(const typename Operation::second_argument_type &x) const
		{
			return op(value, x);
		}
	};

	template <class Operation, class T>
	_UCXXEXPORT binder1st<Operation> bind1st(const Operation &op, const T &x)
	{
		return binder1st<Operation>(op, typename Operation::first_argument_type(x));
	}

	template <class Operation>
	class _UCXXEXPORT binder2nd
		: public unary_function<typename Operation::first_argument_type,
								typename Operation::result_type>
	{
	protected:
		Operation op;
		typename Operation::second_argument_type value;

	public:
		binder2nd(const Operation &x, const typename Operation::second_argument_type &y) : op(x), value(y) {}
		typename Operation::result_type operator()(const typename Operation::first_argument_type &x) const
		{
			return op(x, value);
		}
	};

	template <class Operation, class T>
	_UCXXEXPORT
		binder2nd<Operation>
		bind2nd(const Operation &op, const T &x)
	{
		return binder2nd<Operation>(op, typename Operation::second_argument_type(x));
	}

	template <class Arg, class Result>
	class _UCXXEXPORT
		pointer_to_unary_function : public unary_function<Arg, Result>
	{
	protected:
		Result (*func)(Arg);

	public:
		explicit pointer_to_unary_function(Result (*f)(Arg)) : func(f) {}
		Result operator()(Arg x) const
		{
			return func(x);
		}
	};

	template <class Arg, class Result>
	_UCXXEXPORT pointer_to_unary_function<Arg, Result> ptr_fun(Result (*f)(Arg))
	{
		return pointer_to_unary_function<Arg, Result>(f);
	}

	template <class Arg1, class Arg2, class Result>
	class _UCXXEXPORT
		pointer_to_binary_function : public binary_function<Arg1, Arg2, Result>
	{
	protected:
		Result (*func)(Arg1, Arg2);

	public:
		explicit pointer_to_binary_function(Result (*f)(Arg1, Arg2)) : func(f) {}
		Result operator()(Arg1 x, Arg2 y) const
		{
			return func(x, y);
		}
	};

	template <class Arg1, class Arg2, class Result>
	_UCXXEXPORT
		pointer_to_binary_function<Arg1, Arg2, Result>
		ptr_fun(Result (*f)(Arg1, Arg2))
	{
		return pointer_to_binary_function<Arg1, Arg2, Result>(f);
	}

	template <class S, class T>
	class _UCXXEXPORT mem_fun_t
		: public unary_function<T *, S>
	{
	public:
		explicit mem_fun_t(S (T::*p)()) : m(p) {}
		S operator()(T *p) const { return (p->*m)(); }

	private:
		S (T::*m)();
	};

	template <class S, class T, class A>
	class _UCXXEXPORT mem_fun1_t
		: public binary_function<T *, A, S>
	{
	public:
		explicit mem_fun1_t(S (T::*p)(A)) : m(p) {}
		S operator()(T *p, A x) const { return (p->*m)(x); }

	private:
		S (T::*m)(A);
	};

	template <class S, class T>
	class _UCXXEXPORT const_mem_fun_t
		: public unary_function<const T *, S>
	{
	public:
		explicit const_mem_fun_t(S (T::*p)() const) : m(p) {}
		S operator()(const T *p) const { return (p->*m)(); }

	private:
		S (T::*m)() const;
	};

	template <class S, class T, class A>
	class _UCXXEXPORT const_mem_fun1_t
		: public binary_function<T *, A, S>
	{
	public:
		explicit const_mem_fun1_t(S (T::*p)(A) const) : m(p) {}
		S operator()(const T *p, A x) const { return (p->*m)(x); }

	private:
		S (T::*m)(A) const;
	};

	template <class S, class T>
	_UCXXEXPORT mem_fun_t<S, T> mem_fun(S (T::*f)())
	{
		return mem_fun_t<S, T>(f);
	}

	template <class S, class T>
	_UCXXEXPORT const_mem_fun_t<S, T> mem_fun(S (T::*f)() const)
	{
		return const_mem_fun_t<S, T>(f);
	}

	template <class S, class T, class A>
	_UCXXEXPORT mem_fun1_t<S, T, A> mem_fun(S (T::*f)(A))
	{
		return mem_fun1_t<S, T, A>(f);
	}

	template <class S, class T, class A>
	_UCXXEXPORT const_mem_fun1_t<S, T, A> mem_fun(S (T::*f)(A) const)
	{
		return const_mem_fun1_t<S, T, A>(f);
	}

	template <class S, class T>
	class _UCXXEXPORT mem_fun_ref_t
		: public unary_function<T, S>
	{
	public:
		explicit mem_fun_ref_t(S (T::*p)()) : mf(p) {}
		S operator()(T &p) { return (p.*mf)(); }

	private:
		S (T::*mf)();
	};

	template <class S, class T, class A>
	class _UCXXEXPORT mem_fun1_ref_t
		: public binary_function<T, A, S>
	{
	public:
		explicit mem_fun1_ref_t(S (T::*p)(A)) : mf(p) {}
		S operator()(T &p, A x) { return (p.*mf)(x); }

	private:
		S (T::*mf)(A);
	};

	template <class S, class T>
	_UCXXEXPORT mem_fun_ref_t<S, T> mem_fun_ref(S (T::*f)())
	{
		return mem_fun_ref_t<S, T>(f);
	}

	template <class S, class T, class A>
	_UCXXEXPORT mem_fun1_ref_t<S, T, A> mem_fun1_ref(S (T::*f)(A))
	{
		return mem_fun1_ref_t<S, T, A>(f);
	}
	// 101
#ifdef __cpp_lib_invoke // C++ >= 17

	/** Invoke a callable object.
	 *
	 * `std::invoke` takes a callable object as its first argument and calls it
	 * with the remaining arguments. The callable object can be a pointer or
	 * reference to a function, a lambda closure, a class with `operator()`,
	 * or even a pointer-to-member.  For a pointer-to-member the first argument
	 * must be a reference or pointer to the object that the pointer-to-member
	 * will be applied to.
	 *
	 *  @since C++17
	 */
	template <typename _Callable, typename... _Args>
	inline _GLIBCXX20_CONSTEXPR invoke_result_t<_Callable, _Args...>
	invoke(_Callable &&__fn, _Args &&...__args) noexcept(is_nothrow_invocable_v<_Callable, _Args...>)
	{
		return std::__invoke(std::forward<_Callable>(__fn),
							 std::forward<_Args>(__args)...);
	}
#endif
	// 124
}
#if _GLIBCXX_HOSTED
#include <bits/std_function.h> // std::function
#endif
#if _GLIBCXX_HOSTED
#include <bits/move_only_function.h>
#endif
// These are SGI extensions which are checked for by some conformance checks.  They
//  are *NOT* part of the C++ standard, however

template <class Op1, class Op2>
class _UCXXEXPORT unary_compose : public std::unary_function<typename Op2::argument_type,
															 typename Op1::result_type>
{
protected:
	Op1 mf1;
	Op2 mf2;

public:
	unary_compose(const Op1 &x, const Op2 &y) : mf1(x), mf2(y) {}
	typename Op1::result_type operator()(const typename Op2::argument_type &x) const
	{
		return mf1(mf2(x));
	}
};

template <class Op1, class Op2>
_UCXXEXPORT inline unary_compose<Op1, Op2>
compose1(const Op1 &fn1, const Op2 &fn2)
{
	return unary_compose<Op1, Op2>(fn1, fn2);
}

template <class Op1, class Op2, class Op3>
class _UCXXEXPORT binary_compose : public std::unary_function<typename Op2::argument_type, typename Op1::result_type>
{
protected:
	Op1 mf1;
	Op2 mf2;
	Op3 mf3;

public:
	binary_compose(const Op1 &x, const Op2 &y, const Op3 &z)
		: mf1(x), mf2(y), mf3(z)
	{
	}
	typename Op1::result_type operator()(const typename Op2::argument_type &x) const
	{
		return mf1(mf2(x), mf3(x));
	}
};

template <class Op1, class Op2, class Op3>
inline _UCXXEXPORT binary_compose<Op1, Op2, Op3>
compose2(const Op1 &fn1, const Op2 &fn2, const Op3 &fn3)
{
	return binary_compose<Op1, Op2, Op3>(fn1, fn2, fn3);
}

#pragma GCC visibility pop
#else
#include_next <functional>
#endif
#if __cplusplus < 202002L
#include <bits/move_only_function.h>
#endif
namespace std
{
	// 非标准扩展，为function和move_only_function提供推断指引

	// 主模板，同时也是针对可调用对象（包括lambda）的特化
	template <typename T>
	struct _FunctionSignature : _FunctionSignature<decltype(&T::operator())>
	{
	};
	// 针对函数指针的特化
	template <typename ReturnType, typename... Args>
	struct _FunctionSignature<ReturnType (*)(Args...)>
	{
		using type = ReturnType(Args...) const;
	};
	// 针对成员函数指针的特化
	template <typename ReturnType, typename ClassType, typename... Args>
	struct _FunctionSignature<ReturnType (ClassType::*)(Args...)>
	{
		using type = ReturnType(Args...);
	};
	// 针对const成员函数指针的特化
	template <typename ReturnType, typename ClassType, typename... Args>
	struct _FunctionSignature<ReturnType (ClassType::*)(Args...) const>
	{
		using type = ReturnType(Args...) const;
	};
	template <typename T>
	using _FunctionSignature_t = typename _FunctionSignature<T>::type;

#ifdef __cpp_deduction_guides
	template <typename T>
	function(T) -> function<_FunctionSignature_t<T>>;
	template <typename T>
	move_only_function(T) -> move_only_function<_FunctionSignature_t<T>>;
#endif
}