///////////////////////////////////////////////////////////////////////////// // Copyright (c) Electronic Arts Inc. All rights reserved. ///////////////////////////////////////////////////////////////////////////// #ifndef EASTL_INTERNAL_FUNCTIONAL_BASE_H #define EASTL_INTERNAL_FUNCTIONAL_BASE_H #if defined(EA_PRAGMA_ONCE_SUPPORTED) #pragma once #endif #include #include #include #include namespace eastl { // foward declaration for swap template inline void swap(T& a, T& b) EA_NOEXCEPT_IF(eastl::is_nothrow_move_constructible::value&& eastl::is_nothrow_move_assignable::value); /// invoke /// /// invoke is a generalized function-call operator which works on function pointers, member function /// pointers, callable objects and member pointers. /// /// For (member/non-member) function pointers and callable objects, it returns the result of calling /// the function/object with the specified arguments. For member data pointers, it simply returns /// the member. /// /// Note that there are also reference_wrapper specializations of invoke, which need to be defined /// later since reference_wrapper uses invoke in its implementation. Those are defined immediately /// after the definition of reference_wrapper. /// /// http://en.cppreference.com/w/cpp/utility/functional/invoke /// template auto invoke_impl(R C::*func, T&& obj, Args&&... args) -> typename enable_if>::value, decltype((eastl::forward(obj).*func)(eastl::forward(args)...))>::type { return (eastl::forward(obj).*func)(eastl::forward(args)...); } template auto invoke_impl(F&& func, Args&&... args) -> decltype(eastl::forward(func)(eastl::forward(args)...)) { return eastl::forward(func)(eastl::forward(args)...); } template auto invoke_impl(R C::*func, T&& obj, Args&&... args) -> decltype(((*eastl::forward(obj)).*func)(eastl::forward(args)...)) { return ((*eastl::forward(obj)).*func)(eastl::forward(args)...); } template auto invoke_impl(M C::*member, T&& obj) -> typename enable_if< is_base_of>::value, decltype(obj.*member) >::type { return obj.*member; } template auto invoke_impl(M C::*member, T&& obj) -> decltype((*eastl::forward(obj)).*member) { return (*eastl::forward(obj)).*member; } template inline decltype(auto) invoke(F&& func, Args&&... args) { return invoke_impl(eastl::forward(func), eastl::forward(args)...); } template struct invoke_result_impl { }; template struct invoke_result_impl>(), eastl::declval()...))>, Args...> { typedef decltype(invoke_impl(eastl::declval>(), eastl::declval()...)) type; }; template struct invoke_result : public invoke_result_impl {}; #if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) template using invoke_result_t = typename invoke_result::type; #endif template struct is_invocable_impl : public eastl::false_type {}; template struct is_invocable_impl::type>, Args...> : public eastl::true_type {}; template struct is_invocable : public is_invocable_impl {}; template struct is_invocable_r_impl : public eastl::false_type {}; template struct is_invocable_r_impl::type>, Args...> : public is_convertible::type, R> {}; template struct is_invocable_r : public is_invocable_r_impl {}; #if EASTL_VARIABLE_TEMPLATES_ENABLED template EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_invocable_v = is_invocable::value; template EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_invocable_r_v = is_invocable_r::value; #endif /// allocator_arg_t /// /// allocator_arg_t is an empty class type used to disambiguate the overloads of /// constructors and member functions of allocator-aware objects, including tuple, /// function, promise, and packaged_task. /// http://en.cppreference.com/w/cpp/memory/allocator_arg_t /// struct allocator_arg_t {}; /// allocator_arg /// /// allocator_arg is a constant of type allocator_arg_t used to disambiguate, at call site, /// the overloads of the constructors and member functions of allocator-aware objects, /// such as tuple, function, promise, and packaged_task. /// http://en.cppreference.com/w/cpp/memory/allocator_arg /// #if !defined(EA_COMPILER_NO_CONSTEXPR) EA_CONSTEXPR allocator_arg_t allocator_arg = allocator_arg_t(); #endif template struct unary_function { typedef Argument argument_type; typedef Result result_type; }; template struct binary_function { typedef Argument1 first_argument_type; typedef Argument2 second_argument_type; typedef Result result_type; }; /// less template struct less : public binary_function { EA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const { return a < b; } }; // http://en.cppreference.com/w/cpp/utility/functional/less_void template <> struct less { template EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const -> decltype(eastl::forward(a) < eastl::forward(b)) { return eastl::forward(a) < eastl::forward(b); } }; /// reference_wrapper template class reference_wrapper { public: typedef T type; reference_wrapper(T&) EA_NOEXCEPT; reference_wrapper(T&&) = delete; reference_wrapper(const reference_wrapper& x) EA_NOEXCEPT; reference_wrapper& operator=(const reference_wrapper& x) EA_NOEXCEPT; operator T& () const EA_NOEXCEPT; T& get() const EA_NOEXCEPT; template typename eastl::result_of::type operator() (ArgTypes&&...) const; private: T* val; }; template reference_wrapper::reference_wrapper(T &v) EA_NOEXCEPT : val(eastl::addressof(v)) {} template reference_wrapper::reference_wrapper(const reference_wrapper& other) EA_NOEXCEPT : val(other.val) {} template reference_wrapper& reference_wrapper::operator=(const reference_wrapper& other) EA_NOEXCEPT { val = other.val; return *this; } template reference_wrapper::operator T&() const EA_NOEXCEPT { return *val; } template T& reference_wrapper::get() const EA_NOEXCEPT { return *val; } template template typename eastl::result_of::type reference_wrapper::operator() (ArgTypes&&... args) const { return eastl::invoke(*val, eastl::forward(args)...); } // reference_wrapper-specific utilties template reference_wrapper ref(T& t) EA_NOEXCEPT { return eastl::reference_wrapper(t); } template void ref(const T&&) = delete; template reference_wrapper ref(reference_wrappert) EA_NOEXCEPT { return eastl::ref(t.get()); } template reference_wrapper cref(const T& t) EA_NOEXCEPT { return eastl::reference_wrapper(t); } template void cref(const T&&) = delete; template reference_wrapper cref(reference_wrapper t) EA_NOEXCEPT { return eastl::cref(t.get()); } // reference_wrapper-specific type traits template struct is_reference_wrapper_helper : public eastl::false_type {}; template struct is_reference_wrapper_helper > : public eastl::true_type {}; template struct is_reference_wrapper : public eastl::is_reference_wrapper_helper::type> {}; // Helper which adds a reference to a type when given a reference_wrapper of that type. template struct remove_reference_wrapper { typedef T type; }; template struct remove_reference_wrapper< eastl::reference_wrapper > { typedef T& type; }; template struct remove_reference_wrapper< const eastl::reference_wrapper > { typedef T& type; }; // reference_wrapper specializations of invoke // These have to come after reference_wrapper is defined, but reference_wrapper needs to have a // definition of invoke, so these specializations need to come after everything else has been defined. template auto invoke_impl(R (C::*func)(Args...), T&& obj, Args&&... args) -> typename enable_if::type>::value, decltype((obj.get().*func)(eastl::forward(args)...))>::type { return (obj.get().*func)(eastl::forward(args)...); } template auto invoke_impl(M(C::*member), T&& obj) -> typename enable_if::type>::value, decltype(obj.get().*member)>::type { return obj.get().*member; } /////////////////////////////////////////////////////////////////////// // bind /////////////////////////////////////////////////////////////////////// /// bind1st /// template class binder1st : public unary_function { protected: typename Operation::first_argument_type value; Operation op; public: binder1st(const Operation& x, const typename Operation::first_argument_type& y) : value(y), op(x) { } typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const { return op(value, x); } typename Operation::result_type operator()(typename Operation::second_argument_type& x) const { return op(value, x); } }; template inline binder1st bind1st(const Operation& op, const T& x) { typedef typename Operation::first_argument_type value; return binder1st(op, value(x)); } /// bind2nd /// template class binder2nd : public unary_function { 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); } typename Operation::result_type operator()(typename Operation::first_argument_type& x) const { return op(x, value); } }; template inline binder2nd bind2nd(const Operation& op, const T& x) { typedef typename Operation::second_argument_type value; return binder2nd(op, value(x)); } } // namespace eastl #endif // Header include guard