perfect_forward.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H
  10. #define _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H
  11. #include <__config>
  12. #include <__type_traits/enable_if.h>
  13. #include <__type_traits/invoke.h>
  14. #include <__type_traits/is_constructible.h>
  15. #include <__utility/declval.h>
  16. #include <__utility/forward.h>
  17. #include <__utility/integer_sequence.h>
  18. #include <__utility/move.h>
  19. #include <tuple>
  20. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  21. # pragma GCC system_header
  22. #endif
  23. _LIBCPP_PUSH_MACROS
  24. #include <__undef_macros>
  25. _LIBCPP_BEGIN_NAMESPACE_STD
  26. #if _LIBCPP_STD_VER >= 17
  27. template <class _Op, class _Indices, class... _BoundArgs>
  28. struct __perfect_forward_impl;
  29. template <class _Op, size_t... _Idx, class... _BoundArgs>
  30. struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> {
  31. private:
  32. tuple<_BoundArgs...> __bound_args_;
  33. public:
  34. template <class... _Args, class = enable_if_t<
  35. is_constructible_v<tuple<_BoundArgs...>, _Args&&...>
  36. >>
  37. _LIBCPP_HIDE_FROM_ABI explicit constexpr __perfect_forward_impl(_Args&&... __bound_args)
  38. : __bound_args_(_VSTD::forward<_Args>(__bound_args)...) {}
  39. _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl const&) = default;
  40. _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl&&) = default;
  41. _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl const&) = default;
  42. _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl&&) = default;
  43. template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs&..., _Args...>>>
  44. _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) &
  45. noexcept(noexcept(_Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...)))
  46. -> decltype( _Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...))
  47. { return _Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...); }
  48. template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs&..., _Args...>>>
  49. auto operator()(_Args&&...) & = delete;
  50. template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs const&..., _Args...>>>
  51. _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const&
  52. noexcept(noexcept(_Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...)))
  53. -> decltype( _Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...))
  54. { return _Op()(_VSTD::get<_Idx>(__bound_args_)..., _VSTD::forward<_Args>(__args)...); }
  55. template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs const&..., _Args...>>>
  56. auto operator()(_Args&&...) const& = delete;
  57. template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs..., _Args...>>>
  58. _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) &&
  59. noexcept(noexcept(_Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...)))
  60. -> decltype( _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...))
  61. { return _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...); }
  62. template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs..., _Args...>>>
  63. auto operator()(_Args&&...) && = delete;
  64. template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs const..., _Args...>>>
  65. _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const&&
  66. noexcept(noexcept(_Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...)))
  67. -> decltype( _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...))
  68. { return _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_args_))..., _VSTD::forward<_Args>(__args)...); }
  69. template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs const..., _Args...>>>
  70. auto operator()(_Args&&...) const&& = delete;
  71. };
  72. // __perfect_forward implements a perfect-forwarding call wrapper as explained in [func.require].
  73. template <class _Op, class ..._Args>
  74. using __perfect_forward = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>;
  75. #endif // _LIBCPP_STD_VER >= 17
  76. _LIBCPP_END_NAMESPACE_STD
  77. _LIBCPP_POP_MACROS
  78. #endif // _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H