aboutsummaryrefslogtreecommitdiff
path: root/include/EASTL/functional.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/EASTL/functional.h')
-rw-r--r--include/EASTL/functional.h1266
1 files changed, 1266 insertions, 0 deletions
diff --git a/include/EASTL/functional.h b/include/EASTL/functional.h
new file mode 100644
index 0000000..556bf02
--- /dev/null
+++ b/include/EASTL/functional.h
@@ -0,0 +1,1266 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef EASTL_FUNCTIONAL_H
+#define EASTL_FUNCTIONAL_H
+
+
+#include <EABase/eabase.h>
+#include <EASTL/internal/config.h>
+#include <EASTL/internal/move_help.h>
+#include <EASTL/type_traits.h>
+#include <EASTL/internal/functional_base.h>
+#include <EASTL/internal/mem_fn.h>
+
+
+#if defined(EA_PRAGMA_ONCE_SUPPORTED)
+ #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
+#endif
+
+
+
+namespace eastl
+{
+ ///////////////////////////////////////////////////////////////////////
+ // Primary C++ functions
+ ///////////////////////////////////////////////////////////////////////
+
+ template <typename T = void>
+ struct plus : public binary_function<T, T, T>
+ {
+ EA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const
+ { return a + b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/plus_void
+ template <>
+ struct plus<void>
+ {
+ typedef int is_transparent;
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) + eastl::forward<B>(b))
+ { return eastl::forward<A>(a) + eastl::forward<B>(b); }
+ };
+
+ template <typename T = void>
+ struct minus : public binary_function<T, T, T>
+ {
+ EA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const
+ { return a - b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/minus_void
+ template <>
+ struct minus<void>
+ {
+ typedef int is_transparent;
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) - eastl::forward<B>(b))
+ { return eastl::forward<A>(a) - eastl::forward<B>(b); }
+ };
+
+ template <typename T = void>
+ struct multiplies : public binary_function<T, T, T>
+ {
+ EA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const
+ { return a * b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/multiplies_void
+ template <>
+ struct multiplies<void>
+ {
+ typedef int is_transparent;
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) * eastl::forward<B>(b))
+ { return eastl::forward<A>(a) * eastl::forward<B>(b); }
+ };
+
+ template <typename T = void>
+ struct divides : public binary_function<T, T, T>
+ {
+ EA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const
+ { return a / b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/divides_void
+ template <>
+ struct divides<void>
+ {
+ typedef int is_transparent;
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) / eastl::forward<B>(b))
+ { return eastl::forward<A>(a) / eastl::forward<B>(b); }
+ };
+
+ template <typename T = void>
+ struct modulus : public binary_function<T, T, T>
+ {
+ EA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const
+ { return a % b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/modulus_void
+ template <>
+ struct modulus<void>
+ {
+ typedef int is_transparent;
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) % eastl::forward<B>(b))
+ { return eastl::forward<A>(a) % eastl::forward<B>(b); }
+ };
+
+ template <typename T = void>
+ struct negate : public unary_function<T, T>
+ {
+ EA_CPP14_CONSTEXPR T operator()(const T& a) const
+ { return -a; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/negate_void
+ template <>
+ struct negate<void>
+ {
+ typedef int is_transparent;
+ template<typename T>
+ EA_CPP14_CONSTEXPR auto operator()(T&& t) const
+ -> decltype(-eastl::forward<T>(t))
+ { return -eastl::forward<T>(t); }
+ };
+
+ template <typename T = void>
+ struct equal_to : public binary_function<T, T, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const
+ { return a == b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/equal_to_void
+ template <>
+ struct equal_to<void>
+ {
+ typedef int is_transparent;
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) == eastl::forward<B>(b))
+ { return eastl::forward<A>(a) == eastl::forward<B>(b); }
+ };
+
+ template <typename T, typename Compare>
+ bool validate_equal_to(const T& a, const T& b, Compare compare)
+ {
+ return compare(a, b) == compare(b, a);
+ }
+
+ template <typename T = void>
+ struct not_equal_to : public binary_function<T, T, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const
+ { return a != b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/not_equal_to_void
+ template <>
+ struct not_equal_to<void>
+ {
+ typedef int is_transparent;
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) != eastl::forward<B>(b))
+ { return eastl::forward<A>(a) != eastl::forward<B>(b); }
+ };
+
+ template <typename T, typename Compare>
+ bool validate_not_equal_to(const T& a, const T& b, Compare compare)
+ {
+ return compare(a, b) == compare(b, a); // We want the not equal comparison results to be equal.
+ }
+
+ /// str_equal_to
+ ///
+ /// Compares two 0-terminated string types.
+ /// The T types are expected to be iterators or act like iterators.
+ /// The expected behavior of str_less is the same as (strcmp(p1, p2) == 0).
+ ///
+ /// Example usage:
+ /// hash_set<const char*, hash<const char*>, str_equal_to<const char*> > stringHashSet;
+ ///
+ /// Note:
+ /// You couldn't use str_equal_to like this:
+ /// bool result = equal("hi", "hi" + 2, "ho", str_equal_to<const char*>());
+ /// This is because equal tests an array of something, with each element by
+ /// the comparison function. But str_equal_to tests an array of something itself.
+ ///
+ /// To consider: Update this code to use existing word-based comparison optimizations,
+ /// such as that used in the EAStdC Strcmp function.
+ ///
+ template <typename T>
+ struct str_equal_to : public binary_function<T, T, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(T a, T b) const
+ {
+ while(*a && (*a == *b))
+ {
+ ++a;
+ ++b;
+ }
+ return (*a == *b);
+ }
+ };
+
+ template <typename T = void>
+ struct greater : public binary_function<T, T, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const
+ { return a > b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/greater_void
+ template <>
+ struct greater<void>
+ {
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) > eastl::forward<B>(b))
+ { return eastl::forward<A>(a) > eastl::forward<B>(b); }
+ };
+
+ template <typename T, typename Compare>
+ bool validate_greater(const T& a, const T& b, Compare compare)
+ {
+ return !compare(a, b) || !compare(b, a); // If (a > b), then !(b > a)
+ }
+
+
+ template <typename T, typename Compare>
+ bool validate_less(const T& a, const T& b, Compare compare)
+ {
+ return !compare(a, b) || !compare(b, a); // If (a < b), then !(b < a)
+ }
+
+ /// str_less
+ ///
+ /// Compares two 0-terminated string types.
+ /// The T types are expected to be iterators or act like iterators,
+ /// and that includes being a pointer to a C character array.
+ /// The expected behavior of str_less is the same as (strcmp(p1, p2) < 0).
+ /// This function is not Unicode-correct and it's not guaranteed to work
+ /// with all Unicode strings.
+ ///
+ /// Example usage:
+ /// set<const char*, str_less<const char*> > stringSet;
+ ///
+ /// To consider: Update this code to use existing word-based comparison optimizations,
+ /// such as that used in the EAStdC Strcmp function.
+ ///
+ template <typename T>
+ struct str_less : public binary_function<T, T, bool>
+ {
+ bool operator()(T a, T b) const
+ {
+ while(static_cast<typename make_unsigned<typename remove_pointer<T>::type>::type>(*a) ==
+ static_cast<typename make_unsigned<typename remove_pointer<T>::type>::type>(*b))
+ {
+ if(*a == 0)
+ return (*b != 0);
+ ++a;
+ ++b;
+ }
+
+ char aValue = static_cast<typename remove_pointer<T>::type>(*a);
+ char bValue = static_cast<typename remove_pointer<T>::type>(*b);
+
+ typename make_unsigned<char>::type aValueU = static_cast<typename make_unsigned<char>::type>(aValue);
+ typename make_unsigned<char>::type bValueU = static_cast<typename make_unsigned<char>::type>(bValue);
+
+ return aValueU < bValueU;
+
+ //return (static_cast<typename make_unsigned<typename remove_pointer<T>::type>::type>(*a) <
+ // static_cast<typename make_unsigned<typename remove_pointer<T>::type>::type>(*b));
+ }
+ };
+
+ template <typename T = void>
+ struct greater_equal : public binary_function<T, T, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const
+ { return a >= b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/greater_equal_void
+ template <>
+ struct greater_equal<void>
+ {
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) >= eastl::forward<B>(b))
+ { return eastl::forward<A>(a) >= eastl::forward<B>(b); }
+ };
+
+ template <typename T, typename Compare>
+ bool validate_greater_equal(const T& a, const T& b, Compare compare)
+ {
+ return !compare(a, b) || !compare(b, a); // If (a >= b), then !(b >= a)
+ }
+
+ template <typename T = void>
+ struct less_equal : public binary_function<T, T, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const
+ { return a <= b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/less_equal_void
+ template <>
+ struct less_equal<void>
+ {
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) <= eastl::forward<B>(b))
+ { return eastl::forward<A>(a) <= eastl::forward<B>(b); }
+ };
+
+ template <typename T, typename Compare>
+ bool validate_less_equal(const T& a, const T& b, Compare compare)
+ {
+ return !compare(a, b) || !compare(b, a); // If (a <= b), then !(b <= a)
+ }
+
+ template <typename T = void>
+ struct logical_and : public binary_function<T, T, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const
+ { return a && b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/logical_and_void
+ template <>
+ struct logical_and<void>
+ {
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) && eastl::forward<B>(b))
+ { return eastl::forward<A>(a) && eastl::forward<B>(b); }
+ };
+
+ template <typename T = void>
+ struct logical_or : public binary_function<T, T, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const
+ { return a || b; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/logical_or_void
+ template <>
+ struct logical_or<void>
+ {
+ template<typename A, typename B>
+ EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
+ -> decltype(eastl::forward<A>(a) || eastl::forward<B>(b))
+ { return eastl::forward<A>(a) || eastl::forward<B>(b); }
+ };
+
+ template <typename T = void>
+ struct logical_not : public unary_function<T, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a) const
+ { return !a; }
+ };
+
+ // http://en.cppreference.com/w/cpp/utility/functional/logical_not_void
+ template <>
+ struct logical_not<void>
+ {
+ template<typename T>
+ EA_CPP14_CONSTEXPR auto operator()(T&& t) const
+ -> decltype(!eastl::forward<T>(t))
+ { return !eastl::forward<T>(t); }
+ };
+
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // Dual type functions
+ ///////////////////////////////////////////////////////////////////////
+
+ template <typename T, typename U>
+ struct equal_to_2 : public binary_function<T, U, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const U& b) const
+ { return a == b; }
+ EA_CPP14_CONSTEXPR bool operator()(const U& b, const T& a) const // If you are getting a 'operator() already defined' error related to on this line while compiling a
+ { return b == a; } // hashtable class (e.g. hash_map), it's likely that you are using hashtable::find_as when you should
+ }; // be using hashtable::find instead. The problem is that (const T, U) collide. To do: make this work.
+
+ template <typename T>
+ struct equal_to_2<T, T> : public equal_to<T>
+ {
+ };
+
+
+ template <typename T, typename U>
+ struct not_equal_to_2 : public binary_function<T, U, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const U& b) const
+ { return a != b; }
+ EA_CPP14_CONSTEXPR bool operator()(const U& b, const T& a) const
+ { return b != a; }
+ };
+
+ template <typename T>
+ struct not_equal_to_2<T, T> : public not_equal_to<T>
+ {
+ };
+
+
+ template <typename T, typename U>
+ struct less_2 : public binary_function<T, U, bool>
+ {
+ EA_CPP14_CONSTEXPR bool operator()(const T& a, const U& b) const
+ { return a < b; }
+ EA_CPP14_CONSTEXPR bool operator()(const U& b, const T& a) const
+ { return b < a; }
+ };
+
+ template <typename T>
+ struct less_2<T, T> : public less<T>
+ {
+ };
+
+
+
+
+ /// unary_negate
+ ///
+ template <typename Predicate>
+ class unary_negate : public unary_function<typename Predicate::argument_type, bool>
+ {
+ protected:
+ Predicate mPredicate;
+ public:
+ explicit unary_negate(const Predicate& a)
+ : mPredicate(a) {}
+ EA_CPP14_CONSTEXPR bool operator()(const typename Predicate::argument_type& a) const
+ { return !mPredicate(a); }
+ };
+
+ template <typename Predicate>
+ inline EA_CPP14_CONSTEXPR unary_negate<Predicate> not1(const Predicate& predicate)
+ { return unary_negate<Predicate>(predicate); }
+
+
+
+ /// binary_negate
+ ///
+ template <typename Predicate>
+ class binary_negate : public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool>
+ {
+ protected:
+ Predicate mPredicate;
+ public:
+ explicit binary_negate(const Predicate& a)
+ : mPredicate(a) { }
+ EA_CPP14_CONSTEXPR bool operator()(const typename Predicate::first_argument_type& a, const typename Predicate::second_argument_type& b) const
+ { return !mPredicate(a, b); }
+ };
+
+ template <typename Predicate>
+ inline EA_CPP14_CONSTEXPR binary_negate<Predicate> not2(const Predicate& predicate)
+ { return binary_negate<Predicate>(predicate); }
+
+
+
+ /// unary_compose
+ ///
+ template<typename Operation1, typename Operation2>
+ struct unary_compose : public unary_function<typename Operation2::argument_type, typename Operation1::result_type>
+ {
+ protected:
+ Operation1 op1;
+ Operation2 op2;
+
+ public:
+ unary_compose(const Operation1& x, const Operation2& y)
+ : op1(x), op2(y) {}
+
+ typename Operation1::result_type operator()(const typename Operation2::argument_type& x) const
+ { return op1(op2(x)); }
+
+ typename Operation1::result_type operator()(typename Operation2::argument_type& x) const
+ { return op1(op2(x)); }
+ };
+
+ template<typename Operation1,typename Operation2>
+ inline unary_compose<Operation1,Operation2>
+ compose1(const Operation1& op1, const Operation2& op2)
+ {
+ return unary_compose<Operation1, Operation2>(op1,op2);
+ }
+
+
+ /// binary_compose
+ ///
+ template <class Operation1, class Operation2, class Operation3>
+ class binary_compose : public unary_function<typename Operation2::argument_type, typename Operation1::result_type>
+ {
+ protected:
+ Operation1 op1;
+ Operation2 op2;
+ Operation3 op3;
+
+ public:
+ // Support binary functors too.
+ typedef typename Operation2::argument_type first_argument_type;
+ typedef typename Operation3::argument_type second_argument_type;
+
+ binary_compose(const Operation1& x, const Operation2& y, const Operation3& z)
+ : op1(x), op2(y), op3(z) { }
+
+ typename Operation1::result_type operator()(const typename Operation2::argument_type& x) const
+ { return op1(op2(x),op3(x)); }
+
+ typename Operation1::result_type operator()(typename Operation2::argument_type& x) const
+ { return op1(op2(x),op3(x)); }
+
+ typename Operation1::result_type operator()(const typename Operation2::argument_type& x,const typename Operation3::argument_type& y) const
+ { return op1(op2(x),op3(y)); }
+
+ typename Operation1::result_type operator()(typename Operation2::argument_type& x, typename Operation3::argument_type& y) const
+ { return op1(op2(x),op3(y)); }
+ };
+
+
+ template <class Operation1, class Operation2, class Operation3>
+ inline binary_compose<Operation1, Operation2, Operation3>
+ compose2(const Operation1& op1, const Operation2& op2, const Operation3& op3)
+ {
+ return binary_compose<Operation1, Operation2, Operation3>(op1, op2, op3);
+ }
+
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // pointer_to_unary_function
+ ///////////////////////////////////////////////////////////////////////
+
+ /// pointer_to_unary_function
+ ///
+ /// This is an adapter template which converts a pointer to a standalone
+ /// function to a function object. This allows standalone functions to
+ /// work in many cases where the system requires a function object.
+ ///
+ /// Example usage:
+ /// ptrdiff_t Rand(ptrdiff_t n) { return rand() % n; } // Note: The C rand function is poor and slow.
+ /// pointer_to_unary_function<ptrdiff_t, ptrdiff_t> randInstance(Rand);
+ /// random_shuffle(pArrayBegin, pArrayEnd, randInstance);
+ ///
+ template <typename Arg, typename Result>
+ class pointer_to_unary_function : public unary_function<Arg, Result>
+ {
+ protected:
+ Result (*mpFunction)(Arg);
+
+ public:
+ pointer_to_unary_function()
+ { }
+
+ explicit pointer_to_unary_function(Result (*pFunction)(Arg))
+ : mpFunction(pFunction) { }
+
+ Result operator()(Arg x) const
+ { return mpFunction(x); }
+ };
+
+
+ /// ptr_fun
+ ///
+ /// This ptr_fun is simply shorthand for usage of pointer_to_unary_function.
+ ///
+ /// Example usage (actually, you don't need to use ptr_fun here, but it works anyway):
+ /// int factorial(int x) { return (x > 1) ? (x * factorial(x - 1)) : x; }
+ /// transform(pIntArrayBegin, pIntArrayEnd, pIntArrayBegin, ptr_fun(factorial));
+ ///
+ template <typename Arg, typename Result>
+ inline pointer_to_unary_function<Arg, Result>
+ ptr_fun(Result (*pFunction)(Arg))
+ { return pointer_to_unary_function<Arg, Result>(pFunction); }
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // pointer_to_binary_function
+ ///////////////////////////////////////////////////////////////////////
+
+ /// pointer_to_binary_function
+ ///
+ /// This is an adapter template which converts a pointer to a standalone
+ /// function to a function object. This allows standalone functions to
+ /// work in many cases where the system requires a function object.
+ ///
+ template <typename Arg1, typename Arg2, typename Result>
+ class pointer_to_binary_function : public binary_function<Arg1, Arg2, Result>
+ {
+ protected:
+ Result (*mpFunction)(Arg1, Arg2);
+
+ public:
+ pointer_to_binary_function()
+ { }
+
+ explicit pointer_to_binary_function(Result (*pFunction)(Arg1, Arg2))
+ : mpFunction(pFunction) {}
+
+ Result operator()(Arg1 x, Arg2 y) const
+ { return mpFunction(x, y); }
+ };
+
+
+ /// This ptr_fun is simply shorthand for usage of pointer_to_binary_function.
+ ///
+ /// Example usage (actually, you don't need to use ptr_fun here, but it works anyway):
+ /// int multiply(int x, int y) { return x * y; }
+ /// transform(pIntArray1Begin, pIntArray1End, pIntArray2Begin, pIntArray1Begin, ptr_fun(multiply));
+ ///
+ template <typename Arg1, typename Arg2, typename Result>
+ inline pointer_to_binary_function<Arg1, Arg2, Result>
+ ptr_fun(Result (*pFunction)(Arg1, Arg2))
+ { return pointer_to_binary_function<Arg1, Arg2, Result>(pFunction); }
+
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // mem_fun
+ // mem_fun1
+ //
+ // Note that mem_fun calls member functions via *pointers* to classes
+ // and not instances of classes. mem_fun_ref is for calling functions
+ // via instances of classes or references to classes.
+ //
+ // NOTE:
+ // mem_fun was deprecated in C++11 and removed in C++17, in favor
+ // of the more general mem_fn and bind.
+ //
+ ///////////////////////////////////////////////////////////////////////
+
+ /// mem_fun_t
+ ///
+ /// Member function with no arguments.
+ ///
+ template <typename Result, typename T>
+ class mem_fun_t : public unary_function<T*, Result>
+ {
+ public:
+ typedef Result (T::*MemberFunction)();
+
+ inline explicit mem_fun_t(MemberFunction pMemberFunction)
+ : mpMemberFunction(pMemberFunction)
+ {
+ // Empty
+ }
+
+ inline Result operator()(T* pT) const
+ {
+ return (pT->*mpMemberFunction)();
+ }
+
+ protected:
+ MemberFunction mpMemberFunction;
+ };
+
+
+ /// mem_fun1_t
+ ///
+ /// Member function with one argument.
+ ///
+ template <typename Result, typename T, typename Argument>
+ class mem_fun1_t : public binary_function<T*, Argument, Result>
+ {
+ public:
+ typedef Result (T::*MemberFunction)(Argument);
+
+ inline explicit mem_fun1_t(MemberFunction pMemberFunction)
+ : mpMemberFunction(pMemberFunction)
+ {
+ // Empty
+ }
+
+ inline Result operator()(T* pT, Argument arg) const
+ {
+ return (pT->*mpMemberFunction)(arg);
+ }
+
+ protected:
+ MemberFunction mpMemberFunction;
+ };
+
+
+ /// const_mem_fun_t
+ ///
+ /// Const member function with no arguments.
+ /// Note that we inherit from unary_function<const T*, Result>
+ /// instead of what the C++ standard specifies: unary_function<T*, Result>.
+ /// The C++ standard is in error and this has been recognized by the defect group.
+ ///
+ template <typename Result, typename T>
+ class const_mem_fun_t : public unary_function<const T*, Result>
+ {
+ public:
+ typedef Result (T::*MemberFunction)() const;
+
+ inline explicit const_mem_fun_t(MemberFunction pMemberFunction)
+ : mpMemberFunction(pMemberFunction)
+ {
+ // Empty
+ }
+
+ inline Result operator()(const T* pT) const
+ {
+ return (pT->*mpMemberFunction)();
+ }
+
+ protected:
+ MemberFunction mpMemberFunction;
+ };
+
+
+ /// const_mem_fun1_t
+ ///
+ /// Const member function with one argument.
+ /// Note that we inherit from unary_function<const T*, Result>
+ /// instead of what the C++ standard specifies: unary_function<T*, Result>.
+ /// The C++ standard is in error and this has been recognized by the defect group.
+ ///
+ template <typename Result, typename T, typename Argument>
+ class const_mem_fun1_t : public binary_function<const T*, Argument, Result>
+ {
+ public:
+ typedef Result (T::*MemberFunction)(Argument) const;
+
+ inline explicit const_mem_fun1_t(MemberFunction pMemberFunction)
+ : mpMemberFunction(pMemberFunction)
+ {
+ // Empty
+ }
+
+ inline Result operator()(const T* pT, Argument arg) const
+ {
+ return (pT->*mpMemberFunction)(arg);
+ }
+
+ protected:
+ MemberFunction mpMemberFunction;
+ };
+
+
+ /// mem_fun
+ ///
+ /// This is the high level interface to the mem_fun_t family.
+ ///
+ /// Example usage:
+ /// struct TestClass { void print() { puts("hello"); } }
+ /// TestClass* pTestClassArray[3] = { ... };
+ /// for_each(pTestClassArray, pTestClassArray + 3, &TestClass::print);
+ ///
+ /// Note: using conventional inlining here to avoid issues on GCC/Linux
+ ///
+ template <typename Result, typename T>
+ inline mem_fun_t<Result, T>
+ mem_fun(Result (T::*MemberFunction)())
+ {
+ return eastl::mem_fun_t<Result, T>(MemberFunction);
+ }
+
+ template <typename Result, typename T, typename Argument>
+ inline mem_fun1_t<Result, T, Argument>
+ mem_fun(Result (T::*MemberFunction)(Argument))
+ {
+ return eastl::mem_fun1_t<Result, T, Argument>(MemberFunction);
+ }
+
+ template <typename Result, typename T>
+ inline const_mem_fun_t<Result, T>
+ mem_fun(Result (T::*MemberFunction)() const)
+ {
+ return eastl::const_mem_fun_t<Result, T>(MemberFunction);
+ }
+
+ template <typename Result, typename T, typename Argument>
+ inline const_mem_fun1_t<Result, T, Argument>
+ mem_fun(Result (T::*MemberFunction)(Argument) const)
+ {
+ return eastl::const_mem_fun1_t<Result, T, Argument>(MemberFunction);
+ }
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // mem_fun_ref
+ // mem_fun1_ref
+ //
+ ///////////////////////////////////////////////////////////////////////
+
+ /// mem_fun_ref_t
+ ///
+ template <typename Result, typename T>
+ class mem_fun_ref_t : public unary_function<T, Result>
+ {
+ public:
+ typedef Result (T::*MemberFunction)();
+
+ inline explicit mem_fun_ref_t(MemberFunction pMemberFunction)
+ : mpMemberFunction(pMemberFunction)
+ {
+ // Empty
+ }
+
+ inline Result operator()(T& t) const
+ {
+ return (t.*mpMemberFunction)();
+ }
+
+ protected:
+ MemberFunction mpMemberFunction;
+ };
+
+
+ /// mem_fun1_ref_t
+ ///
+ template <typename Result, typename T, typename Argument>
+ class mem_fun1_ref_t : public binary_function<T, Argument, Result>
+ {
+ public:
+ typedef Result (T::*MemberFunction)(Argument);
+
+ inline explicit mem_fun1_ref_t(MemberFunction pMemberFunction)
+ : mpMemberFunction(pMemberFunction)
+ {
+ // Empty
+ }
+
+ inline Result operator()(T& t, Argument arg) const
+ {
+ return (t.*mpMemberFunction)(arg);
+ }
+
+ protected:
+ MemberFunction mpMemberFunction;
+ };
+
+
+ /// const_mem_fun_ref_t
+ ///
+ template <typename Result, typename T>
+ class const_mem_fun_ref_t : public unary_function<T, Result>
+ {
+ public:
+ typedef Result (T::*MemberFunction)() const;
+
+ inline explicit const_mem_fun_ref_t(MemberFunction pMemberFunction)
+ : mpMemberFunction(pMemberFunction)
+ {
+ // Empty
+ }
+
+ inline Result operator()(const T& t) const
+ {
+ return (t.*mpMemberFunction)();
+ }
+
+ protected:
+ MemberFunction mpMemberFunction;
+ };
+
+
+ /// const_mem_fun1_ref_t
+ ///
+ template <typename Result, typename T, typename Argument>
+ class const_mem_fun1_ref_t : public binary_function<T, Argument, Result>
+ {
+ public:
+ typedef Result (T::*MemberFunction)(Argument) const;
+
+ inline explicit const_mem_fun1_ref_t(MemberFunction pMemberFunction)
+ : mpMemberFunction(pMemberFunction)
+ {
+ // Empty
+ }
+
+ inline Result operator()(const T& t, Argument arg) const
+ {
+ return (t.*mpMemberFunction)(arg);
+ }
+
+ protected:
+ MemberFunction mpMemberFunction;
+ };
+
+
+ /// mem_fun_ref
+ /// Example usage:
+ /// struct TestClass { void print() { puts("hello"); } }
+ /// TestClass testClassArray[3];
+ /// for_each(testClassArray, testClassArray + 3, &TestClass::print);
+ ///
+ /// Note: using conventional inlining here to avoid issues on GCC/Linux
+ ///
+ template <typename Result, typename T>
+ inline mem_fun_ref_t<Result, T>
+ mem_fun_ref(Result (T::*MemberFunction)())
+ {
+ return eastl::mem_fun_ref_t<Result, T>(MemberFunction);
+ }
+
+ template <typename Result, typename T, typename Argument>
+ inline mem_fun1_ref_t<Result, T, Argument>
+ mem_fun_ref(Result (T::*MemberFunction)(Argument))
+ {
+ return eastl::mem_fun1_ref_t<Result, T, Argument>(MemberFunction);
+ }
+
+ template <typename Result, typename T>
+ inline const_mem_fun_ref_t<Result, T>
+ mem_fun_ref(Result (T::*MemberFunction)() const)
+ {
+ return eastl::const_mem_fun_ref_t<Result, T>(MemberFunction);
+ }
+
+ template <typename Result, typename T, typename Argument>
+ inline const_mem_fun1_ref_t<Result, T, Argument>
+ mem_fun_ref(Result (T::*MemberFunction)(Argument) const)
+ {
+ return eastl::const_mem_fun1_ref_t<Result, T, Argument>(MemberFunction);
+ }
+
+
+ // not_fn_ret
+ // not_fn_ret is a implementation specified return type of eastl::not_fn.
+ // The type name is not specified but it does have mandated functions that conforming implementations must support.
+ //
+ // http://en.cppreference.com/w/cpp/utility/functional/not_fn
+ //
+ template <typename F>
+ struct not_fn_ret
+ {
+ explicit not_fn_ret(F&& f) : mDecayF(eastl::forward<F>(f)) {}
+ not_fn_ret(not_fn_ret&& f) = default;
+ not_fn_ret(const not_fn_ret& f) = default;
+
+ // overloads for lvalues
+ template <class... Args>
+ auto operator()(Args&&... args) &
+ -> decltype(!eastl::declval<eastl::invoke_result_t<eastl::decay_t<F>&, Args...>>())
+ { return !eastl::invoke(mDecayF, eastl::forward<Args>(args)...); }
+
+ template <class... Args>
+ auto operator()(Args&&... args) const &
+ -> decltype(!eastl::declval<eastl::invoke_result_t<eastl::decay_t<F> const&, Args...>>())
+ { return !eastl::invoke(mDecayF, eastl::forward<Args>(args)...); }
+
+ // overloads for rvalues
+ template <class... Args>
+ auto operator()(Args&&... args) &&
+ -> decltype(!eastl::declval<eastl::invoke_result_t<eastl::decay_t<F>, Args...>>())
+ { return !eastl::invoke(eastl::move(mDecayF), eastl::forward<Args>(args)...); }
+
+ template <class... Args>
+ auto operator()(Args&&... args) const &&
+ -> decltype(!eastl::declval<eastl::invoke_result_t<eastl::decay_t<F> const, Args...>>())
+ { return !eastl::invoke(eastl::move(mDecayF), eastl::forward<Args>(args)...); }
+
+ eastl::decay_t<F> mDecayF;
+ };
+
+ /// not_fn
+ ///
+ /// Creates an implementation specified functor that returns the complement of the callable object it was passed.
+ /// not_fn is intended to replace the C++03-era negators eastl::not1 and eastl::not2.
+ ///
+ /// http://en.cppreference.com/w/cpp/utility/functional/not_fn
+ ///
+ /// Example usage:
+ ///
+ /// auto nf = eastl::not_fn([]{ return false; });
+ /// assert(nf()); // return true
+ ///
+ template <class F>
+ inline not_fn_ret<F> not_fn(F&& f)
+ {
+ return not_fn_ret<F>(eastl::forward<F>(f));
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // hash
+ ///////////////////////////////////////////////////////////////////////
+ namespace Internal
+ {
+ // utility to disable the generic template specialization that is
+ // used for enum types only.
+ template <typename T, bool Enabled>
+ struct EnableHashIf {};
+
+ template <typename T>
+ struct EnableHashIf<T, true>
+ {
+ size_t operator()(T p) const { return size_t(p); }
+ };
+ } // namespace Internal
+
+
+ template <typename T> struct hash;
+
+ template <typename T>
+ struct hash : Internal::EnableHashIf<T, is_enum_v<T>> {};
+
+ template <typename T> struct hash<T*> // Note that we use the pointer as-is and don't divide by sizeof(T*). This is because the table is of a prime size and this division doesn't benefit distribution.
+ { size_t operator()(T* p) const { return size_t(uintptr_t(p)); } };
+
+ template <> struct hash<bool>
+ { size_t operator()(bool val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<char>
+ { size_t operator()(char val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<signed char>
+ { size_t operator()(signed char val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<unsigned char>
+ { size_t operator()(unsigned char val) const { return static_cast<size_t>(val); } };
+
+ #if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE
+ template <> struct hash<char8_t>
+ { size_t operator()(char8_t val) const { return static_cast<size_t>(val); } };
+ #endif
+
+ #if defined(EA_CHAR16_NATIVE) && EA_CHAR16_NATIVE
+ template <> struct hash<char16_t>
+ { size_t operator()(char16_t val) const { return static_cast<size_t>(val); } };
+ #endif
+
+ #if defined(EA_CHAR32_NATIVE) && EA_CHAR32_NATIVE
+ template <> struct hash<char32_t>
+ { size_t operator()(char32_t val) const { return static_cast<size_t>(val); } };
+ #endif
+
+ // If wchar_t is a native type instead of simply a define to an existing type...
+ #if !defined(EA_WCHAR_T_NON_NATIVE)
+ template <> struct hash<wchar_t>
+ { size_t operator()(wchar_t val) const { return static_cast<size_t>(val); } };
+ #endif
+
+ template <> struct hash<signed short>
+ { size_t operator()(signed short val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<unsigned short>
+ { size_t operator()(unsigned short val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<signed int>
+ { size_t operator()(signed int val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<unsigned int>
+ { size_t operator()(unsigned int val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<signed long>
+ { size_t operator()(signed long val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<unsigned long>
+ { size_t operator()(unsigned long val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<signed long long>
+ { size_t operator()(signed long long val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<unsigned long long>
+ { size_t operator()(unsigned long long val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<float>
+ { size_t operator()(float val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<double>
+ { size_t operator()(double val) const { return static_cast<size_t>(val); } };
+
+ template <> struct hash<long double>
+ { size_t operator()(long double val) const { return static_cast<size_t>(val); } };
+
+ #if defined(EA_HAVE_INT128) && EA_HAVE_INT128
+ template <> struct hash<uint128_t>
+ { size_t operator()(uint128_t val) const { return static_cast<size_t>(val); } };
+ #endif
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // string hashes
+ //
+ // Note that our string hashes here intentionally are slow for long strings.
+ // The reasoning for this is so:
+ // - The large majority of hashed strings are only a few bytes long.
+ // - The hash function is significantly more efficient if it can make this assumption.
+ // - The user is welcome to make a custom hash for those uncommon cases where
+ // long strings need to be hashed. Indeed, the user can probably make a
+ // special hash customized for such strings that's better than what we provide.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <> struct hash<char*>
+ {
+ size_t operator()(const char* p) const
+ {
+ uint32_t c, result = 2166136261U; // FNV1 hash. Perhaps the best string hash. Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while((c = (uint8_t)*p++) != 0) // Using '!=' disables compiler warnings.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+
+ template <> struct hash<const char*>
+ {
+ size_t operator()(const char* p) const
+ {
+ uint32_t c, result = 2166136261U; // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while((c = (uint8_t)*p++) != 0) // cast to unsigned 8 bit.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+
+#if EA_CHAR8_UNIQUE
+ template <> struct hash<char8_t*>
+ {
+ size_t operator()(const char8_t* p) const
+ {
+ uint32_t c, result = 2166136261U; // FNV1 hash. Perhaps the best string hash. Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while((c = (uint8_t)*p++) != 0) // Using '!=' disables compiler warnings.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+
+ template <> struct hash<const char8_t*>
+ {
+ size_t operator()(const char8_t* p) const
+ {
+ uint32_t c, result = 2166136261U; // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while((c = (uint8_t)*p++) != 0) // cast to unsigned 8 bit.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+#endif
+
+
+ template <> struct hash<char16_t*>
+ {
+ size_t operator()(const char16_t* p) const
+ {
+ uint32_t c, result = 2166136261U; // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while((c = (uint16_t)*p++) != 0) // cast to unsigned 16 bit.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+
+ template <> struct hash<const char16_t*>
+ {
+ size_t operator()(const char16_t* p) const
+ {
+ uint32_t c, result = 2166136261U; // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while((c = (uint16_t)*p++) != 0) // cast to unsigned 16 bit.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+
+ template <> struct hash<char32_t*>
+ {
+ size_t operator()(const char32_t* p) const
+ {
+ uint32_t c, result = 2166136261U; // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while((c = (uint32_t)*p++) != 0) // cast to unsigned 32 bit.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+
+ template <> struct hash<const char32_t*>
+ {
+ size_t operator()(const char32_t* p) const
+ {
+ uint32_t c, result = 2166136261U; // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while((c = (uint32_t)*p++) != 0) // cast to unsigned 32 bit.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+
+#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE
+ template<> struct hash<wchar_t*>
+ {
+ size_t operator()(const wchar_t* p) const
+ {
+ uint32_t c, result = 2166136261U; // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while ((c = (uint32_t)*p++) != 0) // cast to unsigned 32 bit.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+
+ template<> struct hash<const wchar_t*>
+ {
+ size_t operator()(const wchar_t* p) const
+ {
+ uint32_t c, result = 2166136261U; // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while ((c = (uint32_t)*p++) != 0) // cast to unsigned 32 bit.
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+#endif
+
+ /// string_hash
+ ///
+ /// Defines a generic string hash for an arbitrary EASTL basic_string container.
+ ///
+ /// Example usage:
+ /// eastl::hash_set<MyString, eastl::string_hash<MyString> > hashSet;
+ ///
+ template <typename String>
+ struct string_hash
+ {
+ typedef String string_type;
+ typedef typename String::value_type value_type;
+ typedef typename eastl::add_unsigned<value_type>::type unsigned_value_type;
+
+ size_t operator()(const string_type& s) const
+ {
+ const unsigned_value_type* p = (const unsigned_value_type*)s.c_str();
+ uint32_t c, result = 2166136261U; // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.
+ while((c = *p++) != 0)
+ result = (result * 16777619) ^ c;
+ return (size_t)result;
+ }
+ };
+
+
+} // namespace eastl
+
+#include <EASTL/internal/function.h>
+
+#endif // Header include guard
+
+
+
+
+
+
+