]>
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> | |
92f5a8d4 | 18 | #include <boost/mp11/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> | |
92f5a8d4 | 67 | return_type<Args&&...> call(mp11::index_sequence<I...>,Args&&... args) |
b32b8144 FG |
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( | |
92f5a8d4 TL |
76 | mp11::make_index_sequence<sizeof...(TailArgs)>{}, |
77 | std::forward<Args>(args)...); | |
b32b8144 FG |
78 | } |
79 | ||
80 | F f; | |
81 | std::tuple<TailArgs...> t; | |
82 | }; | |
83 | ||
84 | template<typename F,typename... Args> | |
85 | tail_closure_class<F,Args&&...> tail_closure(const F& f,Args&&... args) | |
86 | { | |
87 | return {f,std::forward_as_tuple(std::forward<Args>(args)...)}; | |
88 | } | |
89 | ||
90 | template<typename F,typename... HeadArgs> | |
91 | struct head_closure_class | |
92 | { | |
93 | head_closure_class(const F& f,std::tuple<HeadArgs...> t):f(f),t(t){} | |
94 | ||
95 | template<typename... Args> | |
96 | using return_type=decltype( | |
97 | std::declval<F>()(std::declval<HeadArgs>()...,std::declval<Args>()...)); | |
98 | ||
99 | template<typename... Args,std::size_t... I> | |
92f5a8d4 | 100 | return_type<Args&&...> call(mp11::index_sequence<I...>,Args&&... args) |
b32b8144 FG |
101 | { |
102 | return f(std::get<I>(t)...,std::forward<Args>(args)...); | |
103 | } | |
104 | ||
105 | template<typename... Args> | |
106 | return_type<Args&&...> operator()(Args&&... args) | |
107 | { | |
108 | return call( | |
92f5a8d4 TL |
109 | mp11::make_index_sequence<sizeof...(HeadArgs)>{}, |
110 | std::forward<Args>(args)...); | |
b32b8144 FG |
111 | } |
112 | ||
113 | F f; | |
114 | std::tuple<HeadArgs...> t; | |
115 | }; | |
116 | ||
117 | template<typename F,typename... Args> | |
118 | head_closure_class<F,Args&&...> head_closure(const F& f,Args&&... args) | |
119 | { | |
120 | return {f,std::forward_as_tuple(std::forward<Args>(args)...)}; | |
121 | } | |
122 | ||
123 | template<typename ReturnType,typename F> | |
124 | struct cast_return_class | |
125 | { | |
126 | cast_return_class(const F& f):f(f){} | |
127 | ||
128 | template<typename... Args> | |
129 | ReturnType operator()(Args&&... args)const | |
130 | { | |
131 | return static_cast<ReturnType>(f(std::forward<Args>(args)...)); | |
132 | } | |
133 | ||
134 | F f; | |
135 | }; | |
136 | ||
137 | template<typename ReturnType,typename F> | |
138 | cast_return_class<ReturnType,F> cast_return(const F& f) | |
139 | { | |
140 | return {f}; | |
141 | } | |
142 | ||
143 | template<typename F> | |
144 | struct deref_to_class | |
145 | { | |
146 | deref_to_class(const F& f):f(f){} | |
147 | ||
148 | template<typename... Args> | |
149 | auto operator()(Args&&... args)->decltype(std::declval<F>()(*args...)) | |
150 | { | |
151 | return f(*args...); | |
152 | } | |
153 | ||
154 | F f; | |
155 | }; | |
156 | ||
157 | template<typename F> | |
158 | deref_to_class<F> deref_to(const F& f) | |
159 | { | |
160 | return {f}; | |
161 | } | |
162 | ||
163 | template<typename F> | |
164 | struct deref_1st_to_class | |
165 | { | |
166 | deref_1st_to_class(const F& f):f(f){} | |
167 | ||
168 | template<typename Arg,typename... Args> | |
169 | auto operator()(Arg&& arg,Args&&... args) | |
170 | ->decltype(std::declval<F>()(*arg,std::forward<Args>(args)...)) | |
171 | { | |
172 | return f(*arg,std::forward<Args>(args)...); | |
173 | } | |
174 | ||
175 | F f; | |
176 | }; | |
177 | ||
178 | template<typename F> | |
179 | deref_1st_to_class<F> deref_1st_to(const F& f) | |
180 | { | |
181 | return {f}; | |
182 | } | |
183 | ||
184 | struct transparent_equal_to | |
185 | { | |
b32b8144 FG |
186 | template<typename T,typename U> |
187 | auto operator()(T&& x,U&& y)const | |
188 | noexcept(noexcept(std::forward<T>(x)==std::forward<U>(y))) | |
189 | ->decltype(std::forward<T>(x)==std::forward<U>(y)) | |
190 | { | |
191 | return std::forward<T>(x)==std::forward<U>(y); | |
192 | } | |
193 | }; | |
194 | ||
195 | } /* namespace poly_collection::detail */ | |
196 | ||
197 | } /* namespace poly_collection */ | |
198 | ||
199 | } /* namespace boost */ | |
200 | ||
201 | #endif |