Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:47:49

0001 /* Copyright 2016-2018 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/poly_collection for library home page.
0007  */
0008 
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/config.hpp>
0017 #include <boost/detail/workaround.hpp>
0018 #include <boost/mp11/integer_sequence.hpp>
0019 #include <tuple>
0020 #include <utility>
0021 
0022 /* Assorted functional utilities. Much of this would be almost trivial with
0023  * C++14 generic lambdas. 
0024  */
0025 
0026 #if BOOST_WORKAROUND(BOOST_MSVC,>=1910)
0027 /* https://lists.boost.org/Archives/boost/2017/06/235687.php */
0028 
0029 #define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \
0030 struct name                                               \
0031 {                                                         \
0032   template<typename... Args>                              \
0033   auto operator()(Args&&... args)const                    \
0034   {                                                       \
0035     return f(std::forward<Args>(args)...);                \
0036   }                                                       \
0037 };
0038 #else
0039 #define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \
0040 struct name                                               \
0041 {                                                         \
0042   template<typename... Args>                              \
0043   auto operator()(Args&&... args)const->                  \
0044     decltype(f(std::forward<Args>(args)...))              \
0045   {                                                       \
0046     return f(std::forward<Args>(args)...);                \
0047   }                                                       \
0048 };
0049 #endif
0050 
0051 namespace boost{
0052 
0053 namespace poly_collection{
0054 
0055 namespace detail{
0056 
0057 template<typename F,typename... TailArgs>
0058 struct tail_closure_class
0059 {
0060   tail_closure_class(const F& f,std::tuple<TailArgs...> t):f(f),t(t){}
0061 
0062   template<typename... Args>
0063   using return_type=decltype(
0064     std::declval<F>()(std::declval<Args>()...,std::declval<TailArgs>()...));
0065 
0066   template<typename... Args,std::size_t... I>
0067   return_type<Args&&...> call(mp11::index_sequence<I...>,Args&&... args)
0068   {
0069     return f(std::forward<Args>(args)...,std::get<I>(t)...);
0070   }
0071 
0072   template<typename... Args>
0073   return_type<Args&&...> operator()(Args&&... args)
0074   {
0075     return call(
0076       mp11::make_index_sequence<sizeof...(TailArgs)>{},
0077       std::forward<Args>(args)...);
0078   }
0079   
0080   F                       f;
0081   std::tuple<TailArgs...> t; 
0082 };
0083 
0084 template<typename F,typename... Args>
0085 tail_closure_class<F,Args&&...> tail_closure(const F& f,Args&&... args)
0086 {
0087   return {f,std::forward_as_tuple(std::forward<Args>(args)...)};
0088 }
0089 
0090 template<typename F,typename... HeadArgs>
0091 struct head_closure_class
0092 {
0093   head_closure_class(const F& f,std::tuple<HeadArgs...> t):f(f),t(t){}
0094 
0095   template<typename... Args>
0096   using return_type=decltype(
0097     std::declval<F>()(std::declval<HeadArgs>()...,std::declval<Args>()...));
0098 
0099   template<typename... Args,std::size_t... I>
0100   return_type<Args&&...> call(mp11::index_sequence<I...>,Args&&... args)
0101   {
0102     return f(std::get<I>(t)...,std::forward<Args>(args)...);
0103   }
0104 
0105   template<typename... Args>
0106   return_type<Args&&...> operator()(Args&&... args)
0107   {
0108     return call(
0109       mp11::make_index_sequence<sizeof...(HeadArgs)>{},
0110       std::forward<Args>(args)...);
0111   }
0112   
0113   F                       f;
0114   std::tuple<HeadArgs...> t; 
0115 };
0116 
0117 template<typename F,typename... Args>
0118 head_closure_class<F,Args&&...> head_closure(const F& f,Args&&... args)
0119 {
0120   return {f,std::forward_as_tuple(std::forward<Args>(args)...)};
0121 }
0122 
0123 template<typename ReturnType,typename F>
0124 struct cast_return_class
0125 {
0126   cast_return_class(const F& f):f(f){}
0127 
0128   template<typename... Args>
0129   ReturnType operator()(Args&&... args)const
0130   {
0131     return static_cast<ReturnType>(f(std::forward<Args>(args)...));
0132   }
0133 
0134   F f;
0135 };
0136 
0137 template<typename ReturnType,typename F>
0138 cast_return_class<ReturnType,F> cast_return(const F& f)
0139 {
0140   return {f};
0141 }
0142 
0143 template<typename F>
0144 struct deref_to_class
0145 {
0146   deref_to_class(const F& f):f(f){}
0147 
0148   template<typename... Args>
0149   auto operator()(Args&&... args)->decltype(std::declval<F>()(*args...))
0150   {
0151     return f(*args...);
0152   }
0153 
0154   F f;
0155 };
0156 
0157 template<typename F>
0158 deref_to_class<F> deref_to(const F& f)
0159 {
0160   return {f};
0161 }
0162 
0163 template<typename F>
0164 struct deref_1st_to_class
0165 {
0166   deref_1st_to_class(const F& f):f(f){}
0167 
0168   template<typename Arg,typename... Args>
0169   auto operator()(Arg&& arg,Args&&... args)
0170     ->decltype(std::declval<F>()(*arg,std::forward<Args>(args)...))
0171   {
0172     return f(*arg,std::forward<Args>(args)...);
0173   }
0174 
0175   F f;
0176 };
0177 
0178 template<typename F>
0179 deref_1st_to_class<F> deref_1st_to(const F& f)
0180 {
0181   return {f};
0182 }
0183 
0184 struct transparent_equal_to
0185 {
0186   template<typename T,typename U>
0187   auto operator()(T&& x,U&& y)const
0188     noexcept(noexcept(std::forward<T>(x)==std::forward<U>(y)))
0189     ->decltype(std::forward<T>(x)==std::forward<U>(y))
0190   {
0191     return std::forward<T>(x)==std::forward<U>(y);
0192   }
0193 };
0194 
0195 } /* namespace poly_collection::detail */
0196 
0197 } /* namespace poly_collection */
0198 
0199 } /* namespace boost */
0200 
0201 #endif