]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | /* Copyright 2016-2018 Joaquin M Lopez Munoz. |
b32b8144 FG |
2 | * Distributed under the Boost Software License, Version 1.0. |
3 | * (See accompanying file LICENSE_1_0.txt or copy at | |
4 | * http://www.boost.org/LICENSE_1_0.txt) | |
5 | * | |
6 | * See http://www.boost.org/libs/poly_collection for library home page. | |
7 | */ | |
8 | ||
9 | #ifndef BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP | |
10 | #define BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP | |
11 | ||
12 | #if defined(_MSC_VER) | |
13 | #pragma once | |
14 | #endif | |
15 | ||
16 | #include <boost/config.hpp> | |
17 | #include <boost/detail/workaround.hpp> | |
18 | #include <boost/poly_collection/detail/integer_sequence.hpp> | |
b32b8144 FG |
19 | #include <tuple> |
20 | #include <utility> | |
21 | ||
22 | /* Assorted functional utilities. Much of this would be almost trivial with | |
23 | * C++14 generic lambdas. | |
24 | */ | |
25 | ||
26 | #if BOOST_WORKAROUND(BOOST_MSVC,>=1910) | |
27 | /* https://lists.boost.org/Archives/boost/2017/06/235687.php */ | |
28 | ||
29 | #define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \ | |
30 | struct name \ | |
31 | { \ | |
32 | template<typename... Args> \ | |
33 | auto operator()(Args&&... args)const \ | |
34 | { \ | |
35 | return f(std::forward<Args>(args)...); \ | |
36 | } \ | |
37 | }; | |
38 | #else | |
39 | #define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \ | |
40 | struct name \ | |
41 | { \ | |
b32b8144 FG |
42 | template<typename... Args> \ |
43 | auto operator()(Args&&... args)const-> \ | |
44 | decltype(f(std::forward<Args>(args)...)) \ | |
45 | { \ | |
46 | return f(std::forward<Args>(args)...); \ | |
47 | } \ | |
48 | }; | |
49 | #endif | |
50 | ||
51 | namespace boost{ | |
52 | ||
53 | namespace poly_collection{ | |
54 | ||
55 | namespace detail{ | |
56 | ||
57 | template<typename F,typename... TailArgs> | |
58 | struct tail_closure_class | |
59 | { | |
60 | tail_closure_class(const F& f,std::tuple<TailArgs...> t):f(f),t(t){} | |
61 | ||
62 | template<typename... Args> | |
63 | using return_type=decltype( | |
64 | std::declval<F>()(std::declval<Args>()...,std::declval<TailArgs>()...)); | |
65 | ||
66 | template<typename... Args,std::size_t... I> | |
67 | return_type<Args&&...> call(index_sequence<I...>,Args&&... args) | |
68 | { | |
69 | return f(std::forward<Args>(args)...,std::get<I>(t)...); | |
70 | } | |
71 | ||
72 | template<typename... Args> | |
73 | return_type<Args&&...> operator()(Args&&... args) | |
74 | { | |
75 | return call( | |
76 | make_index_sequence<sizeof...(TailArgs)>{},std::forward<Args>(args)...); | |
77 | } | |
78 | ||
79 | F f; | |
80 | std::tuple<TailArgs...> t; | |
81 | }; | |
82 | ||
83 | template<typename F,typename... Args> | |
84 | tail_closure_class<F,Args&&...> tail_closure(const F& f,Args&&... args) | |
85 | { | |
86 | return {f,std::forward_as_tuple(std::forward<Args>(args)...)}; | |
87 | } | |
88 | ||
89 | template<typename F,typename... HeadArgs> | |
90 | struct head_closure_class | |
91 | { | |
92 | head_closure_class(const F& f,std::tuple<HeadArgs...> t):f(f),t(t){} | |
93 | ||
94 | template<typename... Args> | |
95 | using return_type=decltype( | |
96 | std::declval<F>()(std::declval<HeadArgs>()...,std::declval<Args>()...)); | |
97 | ||
98 | template<typename... Args,std::size_t... I> | |
99 | return_type<Args&&...> call(index_sequence<I...>,Args&&... args) | |
100 | { | |
101 | return f(std::get<I>(t)...,std::forward<Args>(args)...); | |
102 | } | |
103 | ||
104 | template<typename... Args> | |
105 | return_type<Args&&...> operator()(Args&&... args) | |
106 | { | |
107 | return call( | |
108 | make_index_sequence<sizeof...(HeadArgs)>{},std::forward<Args>(args)...); | |
109 | } | |
110 | ||
111 | F f; | |
112 | std::tuple<HeadArgs...> t; | |
113 | }; | |
114 | ||
115 | template<typename F,typename... Args> | |
116 | head_closure_class<F,Args&&...> head_closure(const F& f,Args&&... args) | |
117 | { | |
118 | return {f,std::forward_as_tuple(std::forward<Args>(args)...)}; | |
119 | } | |
120 | ||
121 | template<typename ReturnType,typename F> | |
122 | struct cast_return_class | |
123 | { | |
124 | cast_return_class(const F& f):f(f){} | |
125 | ||
126 | template<typename... Args> | |
127 | ReturnType operator()(Args&&... args)const | |
128 | { | |
129 | return static_cast<ReturnType>(f(std::forward<Args>(args)...)); | |
130 | } | |
131 | ||
132 | F f; | |
133 | }; | |
134 | ||
135 | template<typename ReturnType,typename F> | |
136 | cast_return_class<ReturnType,F> cast_return(const F& f) | |
137 | { | |
138 | return {f}; | |
139 | } | |
140 | ||
141 | template<typename F> | |
142 | struct deref_to_class | |
143 | { | |
144 | deref_to_class(const F& f):f(f){} | |
145 | ||
146 | template<typename... Args> | |
147 | auto operator()(Args&&... args)->decltype(std::declval<F>()(*args...)) | |
148 | { | |
149 | return f(*args...); | |
150 | } | |
151 | ||
152 | F f; | |
153 | }; | |
154 | ||
155 | template<typename F> | |
156 | deref_to_class<F> deref_to(const F& f) | |
157 | { | |
158 | return {f}; | |
159 | } | |
160 | ||
161 | template<typename F> | |
162 | struct deref_1st_to_class | |
163 | { | |
164 | deref_1st_to_class(const F& f):f(f){} | |
165 | ||
166 | template<typename Arg,typename... Args> | |
167 | auto operator()(Arg&& arg,Args&&... args) | |
168 | ->decltype(std::declval<F>()(*arg,std::forward<Args>(args)...)) | |
169 | { | |
170 | return f(*arg,std::forward<Args>(args)...); | |
171 | } | |
172 | ||
173 | F f; | |
174 | }; | |
175 | ||
176 | template<typename F> | |
177 | deref_1st_to_class<F> deref_1st_to(const F& f) | |
178 | { | |
179 | return {f}; | |
180 | } | |
181 | ||
182 | struct transparent_equal_to | |
183 | { | |
b32b8144 FG |
184 | template<typename T,typename U> |
185 | auto operator()(T&& x,U&& y)const | |
186 | noexcept(noexcept(std::forward<T>(x)==std::forward<U>(y))) | |
187 | ->decltype(std::forward<T>(x)==std::forward<U>(y)) | |
188 | { | |
189 | return std::forward<T>(x)==std::forward<U>(y); | |
190 | } | |
191 | }; | |
192 | ||
193 | } /* namespace poly_collection::detail */ | |
194 | ||
195 | } /* namespace poly_collection */ | |
196 | ||
197 | } /* namespace boost */ | |
198 | ||
199 | #endif |