dlib C++ Library - functional.h

// Copyright (C) 2021 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_FUNCTIONAL_Hh_
#define DLIB_FUNCTIONAL_Hh_
#include <functional>
#include "type_traits.h"
#include "utility.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
 namespace detail 
 {
 template< typename T >
 struct is_reference_wrapper : std::false_type {};
 template< typename U >
 struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type {};
 template <
 typename Base,
 typename T,
 typename Derived,
 typename... Args
 >
 constexpr auto invoke_(
 T Base::*pmf, //pointer to member function
 Derived&& ref,
 Args&&... args
 )
 noexcept(noexcept((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...)))
 -> typename std::enable_if<
 std::is_function<T>::value &&
 std::is_base_of<Base, typename std::decay<Derived>::type>::value,
 decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))
 >::type
 {
 return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...);
 }
 template<
 typename Base,
 typename T,
 typename RefWrap,
 typename... Args
 >
 constexpr auto invoke_(
 T Base::*pmf, //pointer to member function
 RefWrap&& ref,
 Args&&... args
 )
 noexcept(noexcept((ref.get().*pmf)(std::forward<Args>(args)...)))
 -> typename std::enable_if<
 std::is_function<T>::value &&
 is_reference_wrapper<typename std::decay<RefWrap>::type>::value,
 decltype((ref.get().*pmf)(std::forward<Args>(args)...))>::type
 {
 return (ref.get().*pmf)(std::forward<Args>(args)...);
 }
 template<
 typename Base,
 typename T,
 typename Ptr,
 typename... Args
 >
 constexpr auto invoke_(
 T Base::*pmf, //pointer to member function
 Ptr&& ptr,
 Args&&... args
 )
 noexcept(noexcept(((*std::forward<Ptr>(ptr)).*pmf)( std::forward<Args>( args )...)))
 -> typename std::enable_if<
 std::is_function<T>::value &&
 !is_reference_wrapper<typename std::decay<Ptr>::type>::value &&
 !std::is_base_of<Base, typename std::decay<Ptr>::type>::value,
 decltype(((*std::forward<Ptr>(ptr)).*pmf)(std::forward<Args>(args)...))>::type
 {
 return ((*std::forward<Ptr>(ptr)).*pmf)( std::forward<Args>( args )...);
 }
 template<
 typename Base,
 typename T,
 typename Derived
 >
 constexpr auto invoke_(
 T Base::*pmd, //pointer to member data
 Derived&& ref
 )
 noexcept(noexcept(std::forward<Derived>(ref).*pmd))
 -> typename std::enable_if<
 std::is_object<T>::value &&
 std::is_base_of<Base, typename std::decay<Derived>::type>::value,
 decltype(std::forward<Derived>(ref).*pmd)>::type
 {
 return std::forward<Derived>(ref).*pmd;
 }
 template<
 typename Base,
 typename T,
 typename RefWrap
 >
 constexpr auto invoke_(
 T Base::*pmd, //pointer to member data
 RefWrap&& ref
 )
 noexcept(noexcept(ref.get().*pmd))
 -> typename std::enable_if<
 std::is_object<T>::value &&
 is_reference_wrapper<typename std::decay<RefWrap>::type>::value,
 decltype(ref.get().*pmd)>::type
 {
 return ref.get().*pmd;
 }
 template<
 typename Base,
 typename T,
 typename Ptr
 >
 constexpr auto invoke_(
 T Base::*pmd, //pointer to member data
 Ptr&& ptr
 )
 noexcept(noexcept((*std::forward<Ptr>(ptr)).*pmd))
 -> typename std::enable_if<
 std::is_object<T>::value &&
 !is_reference_wrapper<typename std::decay<Ptr>::type>::value &&
 !std::is_base_of<Base, typename std::decay<Ptr>::type>::value,
 decltype((*std::forward<Ptr>(ptr)).*pmd)>::type
 {
 return (*std::forward<Ptr>(ptr)).*pmd;
 }
 template<
 typename F,
 typename... Args
 >
 constexpr auto invoke_(
 F && f,
 Args&&... args
 )
 noexcept(noexcept(std::forward<F>( f )( std::forward<Args>( args )...)))
 -> typename std::enable_if<
 !std::is_member_pointer<typename std::decay<F>::type>::value,
 decltype(std::forward<F>(f)(std::forward<Args>(args)...))>::type
 {
 return std::forward<F>( f )( std::forward<Args>( args )...);
 }
 } // end namespace detail
// ----------------------------------------------------------------------------------------
 
 template< typename F, typename... Args>
 constexpr auto invoke(F && f, Args &&... args)
 /*!
 ensures
 - identical to std::invoke(std::forward<F>(f), std::forward<Args>(args)...)
 - works with C++11 onwards
 !*/
 noexcept(noexcept(detail::invoke_(std::forward<F>( f ), std::forward<Args>( args )...)))
 -> decltype(detail::invoke_(std::forward<F>( f ), std::forward<Args>( args )...))
 {
 return detail::invoke_(std::forward<F>( f ), std::forward<Args>( args )...);
 }
// ----------------------------------------------------------------------------------------
 namespace detail
 {
 template<class AlwaysVoid, class F, class... Args>
 struct invoke_traits
 {
 static constexpr bool value{false};
 template<class R>
 using is_convertible = std::false_type;
 };
 template<class F, class... Args>
 struct invoke_traits<void_t<decltype(dlib::invoke(std::declval<F>(), std::declval<Args>()...))>, F, Args...>
 {
 static constexpr bool value{true};
 using type = decltype(dlib::invoke(std::declval<F>(), std::declval<Args>()...));
 template<class R>
 using is_convertible = std::is_convertible<type, R>;
 };
 } // end namespace detail
// ----------------------------------------------------------------------------------------
 template< typename F, typename... Args >
 struct invoke_result : detail::invoke_traits< void, F, Args...> {};
 /*!
 ensures
 - identical to std::invoke_result<F, Args..>
 - works with C++11 onwards
 !*/
 template< typename F, typename... Args >
 using invoke_result_t = typename invoke_result<F, Args...>::type;
 /*!
 ensures
 - identical to std::invoke_result_t<F, Args..>
 - works with C++11 onwards
 !*/
// ----------------------------------------------------------------------------------------
 template< typename F, typename... Args >
 struct is_invocable : std::integral_constant<bool, detail::invoke_traits< void, F, Args...>::value> {};
 /*!
 ensures
 - identical to std::is_invocable<F, Args..>
 - works with C++11 onwards
 !*/
// ----------------------------------------------------------------------------------------
 template <typename R, typename F, typename... Args>
 struct is_invocable_r : std::integral_constant<bool, detail::invoke_traits< void, F, Args...>::template is_convertible<R>::value> {};
 /*!
 ensures
 - identical to std::is_invocable_r<R, F, Args..>
 - works with C++11 onwards
 !*/
// ----------------------------------------------------------------------------------------
 template< typename R, typename F, typename... Args>
 constexpr typename std::enable_if<dlib::is_invocable_r<R, F, Args...>::value, R>::type
 invoke_r(F && f, Args &&... args)
 /*!
 ensures
 - identical to std::invoke_r<R>(std::forward<F>(f), std::forward<Args>(args)...)
 - works with C++11 onwards
 !*/
 noexcept(noexcept(dlib::invoke(std::forward<F>( f ), std::forward<Args>( args )...)))
 {
 return dlib::invoke(std::forward<F>( f ), std::forward<Args>( args )...);
 }
// ----------------------------------------------------------------------------------------
 namespace detail
 {
 template<typename F, typename Tuple, std::size_t... I>
 constexpr auto apply_impl(F&& fn, Tuple&& tpl, index_sequence<I...>)
 noexcept(noexcept(dlib::invoke(std::forward<F>(fn),
 std::get<I>(std::forward<Tuple>(tpl))...)))
 -> decltype(dlib::invoke(std::forward<F>(fn),
 std::get<I>(std::forward<Tuple>(tpl))...))
 {
 return dlib::invoke(std::forward<F>(fn),
 std::get<I>(std::forward<Tuple>(tpl))...);
 }
 } // end namespace detail
// ----------------------------------------------------------------------------------------
 template<typename F, typename Tuple>
 constexpr auto apply(F&& fn, Tuple&& tpl)
 /*!
 ensures
 - identical to std::apply(std::forward<F>(f), std::forward<Tuple>(tpl))
 - works with C++11 onwards
 !*/
 noexcept(noexcept(detail::apply_impl(std::forward<F>(fn),
 std::forward<Tuple>(tpl),
 make_index_sequence<std::tuple_size<typename std::remove_reference<Tuple>::type >::value>{})))
 -> decltype(detail::apply_impl(std::forward<F>(fn),
 std::forward<Tuple>(tpl),
 make_index_sequence<std::tuple_size<typename std::remove_reference<Tuple>::type >::value>{}))
 {
 return detail::apply_impl(std::forward<F>(fn),
 std::forward<Tuple>(tpl),
 make_index_sequence<std::tuple_size<typename std::remove_reference<Tuple>::type >::value>{});
 }
// ----------------------------------------------------------------------------------------
 namespace detail
 {
 template <class T, class Tuple, std::size_t... I>
 constexpr T make_from_tuple_impl( Tuple&& t, index_sequence<I...> )
 {
 return T(std::get<I>(std::forward<Tuple>(t))...);
 }
 } // end namespace detail
// ----------------------------------------------------------------------------------------
 template <class T, class Tuple>
 constexpr T make_from_tuple( Tuple&& t )
 /*!
 ensures
 - identical to std::make_from_tuple<T>(std::forward<Tuple>(t))
 - works with C++11 onwards
 !*/
 {
 return detail::make_from_tuple_impl<T>(std::forward<Tuple>(t),
 make_index_sequence<std::tuple_size<typename std::remove_reference<Tuple>::type >::value>{});
 }
// ----------------------------------------------------------------------------------------
 namespace detail
 {
 template<class Binder, std::size_t ...I, class ...Rest>
 constexpr static auto binder_run(
 Binder&& self,
 std::integral_constant<bool, false>,
 index_sequence<I...>, 
 Rest&&... rest
 ) noexcept(noexcept(dlib::invoke(std::forward<Binder>(self).func, std::get<I>(std::forward<Binder>(self).args)..., std::forward<Rest>(rest)...)))
 -> decltype(dlib::invoke(std::forward<Binder>(self).func, std::get<I>(std::forward<Binder>(self).args)..., std::forward<Rest>(rest)...))
 {
 return dlib::invoke(std::forward<Binder>(self).func, std::get<I>(std::forward<Binder>(self).args)..., std::forward<Rest>(rest)...);
 }
 template<class Binder, std::size_t ...I, class ...Rest>
 constexpr static auto binder_run(
 Binder&& self,
 std::integral_constant<bool, true>,
 index_sequence<I...>, 
 Rest&&... rest
 ) noexcept(noexcept(dlib::invoke(std::forward<Binder>(self).func, std::forward<Rest>(rest)..., std::get<I>(std::forward<Binder>(self).args)...)))
 -> decltype(dlib::invoke(std::forward<Binder>(self).func, std::forward<Rest>(rest)..., std::get<I>(std::forward<Binder>(self).args)...))
 {
 return dlib::invoke(std::forward<Binder>(self).func, std::forward<Rest>(rest)..., std::get<I>(std::forward<Binder>(self).args)...);
 }
 template<bool Back, class F, class ...Args>
 struct binder_wrapper
 {
 F func;
 std::tuple<Args...> args;
 template<class ...Rest>
 constexpr auto operator()(Rest&&... rest) 
 noexcept(noexcept(binder_run(std::declval<binder_wrapper&>(), std::integral_constant<bool, Back>{}, index_sequence_for<Args...>{}, std::forward<Rest>(rest)...)))
 -> decltype(binder_run(std::declval<binder_wrapper&>(), std::integral_constant<bool, Back>{}, index_sequence_for<Args...>{}, std::forward<Rest>(rest)...))
 {
 return binder_run(*this, std::integral_constant<bool, Back>{}, index_sequence_for<Args...>{}, std::forward<Rest>(rest)...);
 }
 };
 template<bool Back, class F, class... Args>
 constexpr auto make_binder(
 F&& func, 
 Args&&... args
 )
 {
 return binder_wrapper<Back, std::decay_t<F>, std::decay_t<Args>...>{std::forward<F>(func), std::make_tuple(std::forward<Args>(args)...)};
 }
 }
 
 template<class F, class ...Args>
 constexpr auto bind_front(
 F&& func,
 Args&&... args
 ) noexcept(noexcept(detail::make_binder<false>(std::forward<F>(func), std::forward<Args>(args)...)))
 /*!
 ensures
 - identical to std::bind_front()
 - works with C++11 onwards
 !*/
 {
 return detail::make_binder<false>(std::forward<F>(func), std::forward<Args>(args)...);
 }
 template<class F, class ...Args>
 constexpr auto bind_back(
 F&& func,
 Args&&... args
 ) noexcept(noexcept(detail::make_binder<true>(std::forward<F>(func), std::forward<Args>(args)...)))
 /*!
 ensures
 - identical to std::bind_back()
 - works with C++11 onwards
 !*/
 {
 return detail::make_binder<true>(std::forward<F>(func), std::forward<Args>(args)...);
 }
// ----------------------------------------------------------------------------------------
}
#endif //DLIB_FUNCTIONAL_Hh_

AltStyle によって変換されたページ (->オリジナル) /