|
15 | 15 |
|
16 | 16 | #include "config.hpp"
|
17 | 17 |
|
18 |
| -#define MPARK_RETURN(...) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } |
| 18 | +#define MPARK_RETURN(...) \ |
| 19 | + noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } |
19 | 20 |
|
20 | 21 | namespace mpark {
|
21 | 22 | namespace lib {
|
@@ -205,48 +206,107 @@ namespace mpark {
|
205 | 206 | static constexpr bool value = decltype(test<T>(0))::value;
|
206 | 207 | };
|
207 | 208 |
|
208 |
| - template <typename T, bool = is_swappable<T>::value> |
| 209 | + template <bool IsSwappable, typename T> |
209 | 210 | struct is_nothrow_swappable {
|
210 | 211 | static constexpr bool value =
|
211 | 212 | noexcept(swap(std::declval<T &>(), std::declval<T &>()));
|
212 | 213 | };
|
213 | 214 |
|
214 | 215 | template <typename T>
|
215 |
| - struct is_nothrow_swappable<T, false> : std::false_type {}; |
| 216 | + struct is_nothrow_swappable<false, T> : std::false_type {}; |
216 | 217 |
|
217 | 218 | } // namespace swappable
|
218 | 219 | } // namespace detail
|
219 | 220 |
|
220 | 221 | using detail::swappable::is_swappable;
|
221 |
| - using detail::swappable::is_nothrow_swappable; |
| 222 | + |
| 223 | + template <typename T> |
| 224 | + using is_nothrow_swappable = |
| 225 | + detail::swappable::is_nothrow_swappable<is_swappable<T>::value, T>; |
222 | 226 |
|
223 | 227 | // <functional>
|
| 228 | + namespace detail { |
| 229 | + |
| 230 | + template <typename T> |
| 231 | + struct is_reference_wrapper : std::false_type {}; |
| 232 | + |
| 233 | + template <typename T> |
| 234 | + struct is_reference_wrapper<std::reference_wrapper<T>> |
| 235 | + : std::true_type {}; |
| 236 | + |
| 237 | + template <bool, int> |
| 238 | + struct Invoke; |
| 239 | + |
| 240 | + template <> |
| 241 | + struct Invoke<true /* pmf */, 0 /* is_base_of */> { |
| 242 | + template <typename R, typename T, typename Arg, typename... Args> |
| 243 | + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) |
| 244 | + MPARK_RETURN((lib::forward<Arg>(arg).*pmf)(lib::forward<Args>(args)...)) |
| 245 | + }; |
| 246 | + |
| 247 | + template <> |
| 248 | + struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> { |
| 249 | + template <typename R, typename T, typename Arg, typename... Args> |
| 250 | + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) |
| 251 | + MPARK_RETURN((lib::forward<Arg>(arg).get().*pmf)(lib::forward<Args>(args)...)) |
| 252 | + }; |
| 253 | + |
| 254 | + template <> |
| 255 | + struct Invoke<true /* pmf */, 2 /* otherwise */> { |
| 256 | + template <typename R, typename T, typename Arg, typename... Args> |
| 257 | + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) |
| 258 | + MPARK_RETURN(((*lib::forward<Arg>(arg)).*pmf)(lib::forward<Args>(args)...)) |
| 259 | + }; |
| 260 | + |
| 261 | + template <> |
| 262 | + struct Invoke<false /* pmo */, 0 /* is_base_of */> { |
| 263 | + template <typename R, typename T, typename Arg> |
| 264 | + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) |
| 265 | + MPARK_RETURN(lib::forward<Arg>(arg).*pmo) |
| 266 | + }; |
| 267 | + |
| 268 | + template <> |
| 269 | + struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> { |
| 270 | + template <typename R, typename T, typename Arg> |
| 271 | + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) |
| 272 | + MPARK_RETURN(lib::forward<Arg>(arg).get().*pmo) |
| 273 | + }; |
| 274 | + |
| 275 | + template <> |
| 276 | + struct Invoke<false /* pmo */, 2 /* otherwise */> { |
| 277 | + template <typename R, typename T, typename Arg> |
| 278 | + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) |
| 279 | + MPARK_RETURN((*lib::forward<Arg>(arg)).*pmo) |
| 280 | + }; |
| 281 | + |
| 282 | + template <typename R, typename T, typename Arg, typename... Args> |
| 283 | + inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) |
| 284 | + MPARK_RETURN( |
| 285 | + Invoke<std::is_function<R>::value, |
| 286 | + (std::is_base_of<T, lib::decay_t<Arg>>::value |
| 287 | + ? 0 |
| 288 | + : is_reference_wrapper<lib::decay_t<Arg>>::value |
| 289 | + ? 1 |
| 290 | + : 2)>::invoke(f, |
| 291 | + lib::forward<Arg>(arg), |
| 292 | + lib::forward<Args>(args)...)) |
| 293 | + |
224 | 294 | #ifdef _MSC_VER
|
225 | 295 | #pragma warning(push)
|
226 | 296 | #pragma warning(disable : 4100)
|
227 | 297 | #endif
|
228 |
| - template <typename F, typename... As> |
229 |
| - inline constexpr auto invoke(F &&f, As &&... as) |
230 |
| - MPARK_RETURN(lib::forward<F>(f)(lib::forward<As>(as)...)) |
| 298 | + template <typename F, typename... Args> |
| 299 | + inline constexpr auto invoke(F &&f, Args &&... args) |
| 300 | + MPARK_RETURN(lib::forward<F>(f)(lib::forward<Args>(args)...)) |
231 | 301 | #ifdef _MSC_VER
|
232 | 302 | #pragma warning(pop)
|
233 | 303 | #endif
|
| 304 | + } // namespace detail |
234 | 305 |
|
235 |
| - template <typename B, typename T, typename D> |
236 |
| - inline constexpr auto invoke(T B::*pmv, D &&d) |
237 |
| - MPARK_RETURN(lib::forward<D>(d).*pmv) |
238 |
| - |
239 |
| - template <typename Pmv, typename Ptr> |
240 |
| - inline constexpr auto invoke(Pmv pmv, Ptr &&ptr) |
241 |
| - MPARK_RETURN((*lib::forward<Ptr>(ptr)).*pmv) |
242 |
| - |
243 |
| - template <typename B, typename T, typename D, typename... As> |
244 |
| - inline constexpr auto invoke(T B::*pmf, D &&d, As &&... as) |
245 |
| - MPARK_RETURN((lib::forward<D>(d).*pmf)(lib::forward<As>(as)...)) |
246 |
| - |
247 |
| - template <typename Pmf, typename Ptr, typename... As> |
248 |
| - inline constexpr auto invoke(Pmf pmf, Ptr &&ptr, As &&... as) |
249 |
| - MPARK_RETURN(((*lib::forward<Ptr>(ptr)).*pmf)(lib::forward<As>(as)...)) |
| 306 | + template <typename F, typename... Args> |
| 307 | + inline constexpr auto invoke(F &&f, Args &&... args) |
| 308 | + MPARK_RETURN(detail::invoke(lib::forward<F>(f), |
| 309 | + lib::forward<Args>(args)...)) |
250 | 310 |
|
251 | 311 | namespace detail {
|
252 | 312 |
|
@@ -296,6 +356,44 @@ namespace mpark {
|
296 | 356 | template <typename R, typename F, typename... Args>
|
297 | 357 | using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
|
298 | 358 |
|
| 359 | + namespace detail { |
| 360 | + |
| 361 | + template <bool Invocable, typename F, typename... Args> |
| 362 | + struct is_nothrow_invocable { |
| 363 | + static constexpr bool value = |
| 364 | + noexcept(lib::invoke(std::declval<F>(), std::declval<Args>()...)); |
| 365 | + }; |
| 366 | + |
| 367 | + template <typename F, typename... Args> |
| 368 | + struct is_nothrow_invocable<false, F, Args...> : std::false_type {}; |
| 369 | + |
| 370 | + template <bool Invocable, typename R, typename F, typename... Args> |
| 371 | + struct is_nothrow_invocable_r { |
| 372 | + private: |
| 373 | + inline static R impl() { |
| 374 | + return lib::invoke(std::declval<F>(), std::declval<Args>()...); |
| 375 | + } |
| 376 | + |
| 377 | + public: |
| 378 | + static constexpr bool value = noexcept(impl()); |
| 379 | + }; |
| 380 | + |
| 381 | + template <typename R, typename F, typename... Args> |
| 382 | + struct is_nothrow_invocable_r<false, R, F, Args...> : std::false_type {}; |
| 383 | + |
| 384 | + } // namespace detail |
| 385 | + |
| 386 | + template <typename F, typename... Args> |
| 387 | + using is_nothrow_invocable = detail:: |
| 388 | + is_nothrow_invocable<is_invocable<F, Args...>::value, F, Args...>; |
| 389 | + |
| 390 | + template <typename R, typename F, typename... Args> |
| 391 | + using is_nothrow_invocable_r = |
| 392 | + detail::is_nothrow_invocable_r<is_invocable_r<R, F, Args...>::value, |
| 393 | + R, |
| 394 | + F, |
| 395 | + Args...>; |
| 396 | + |
299 | 397 | // <memory>
|
300 | 398 | #ifdef MPARK_BUILTIN_ADDRESSOF
|
301 | 399 | template <typename T>
|
|
0 commit comments