front_binder.h 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright 2018 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Implementation details for `y_absl::bind_front()`.
  15. #ifndef Y_ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_
  16. #define Y_ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_
  17. #include <cstddef>
  18. #include <type_traits>
  19. #include <utility>
  20. #include "y_absl/base/internal/invoke.h"
  21. #include "y_absl/container/internal/compressed_tuple.h"
  22. #include "y_absl/meta/type_traits.h"
  23. #include "y_absl/utility/utility.h"
  24. namespace y_absl {
  25. Y_ABSL_NAMESPACE_BEGIN
  26. namespace functional_internal {
  27. // Invoke the method, expanding the tuple of bound arguments.
  28. template <class R, class Tuple, size_t... Idx, class... Args>
  29. R Apply(Tuple&& bound, y_absl::index_sequence<Idx...>, Args&&... free) {
  30. return base_internal::invoke(
  31. std::forward<Tuple>(bound).template get<Idx>()...,
  32. std::forward<Args>(free)...);
  33. }
  34. template <class F, class... BoundArgs>
  35. class FrontBinder {
  36. using BoundArgsT = y_absl::container_internal::CompressedTuple<F, BoundArgs...>;
  37. using Idx = y_absl::make_index_sequence<sizeof...(BoundArgs) + 1>;
  38. BoundArgsT bound_args_;
  39. public:
  40. template <class... Ts>
  41. constexpr explicit FrontBinder(y_absl::in_place_t, Ts&&... ts)
  42. : bound_args_(std::forward<Ts>(ts)...) {}
  43. template <class... FreeArgs, class R = base_internal::invoke_result_t<
  44. F&, BoundArgs&..., FreeArgs&&...>>
  45. R operator()(FreeArgs&&... free_args) & {
  46. return functional_internal::Apply<R>(bound_args_, Idx(),
  47. std::forward<FreeArgs>(free_args)...);
  48. }
  49. template <class... FreeArgs,
  50. class R = base_internal::invoke_result_t<
  51. const F&, const BoundArgs&..., FreeArgs&&...>>
  52. R operator()(FreeArgs&&... free_args) const& {
  53. return functional_internal::Apply<R>(bound_args_, Idx(),
  54. std::forward<FreeArgs>(free_args)...);
  55. }
  56. template <class... FreeArgs, class R = base_internal::invoke_result_t<
  57. F&&, BoundArgs&&..., FreeArgs&&...>>
  58. R operator()(FreeArgs&&... free_args) && {
  59. // This overload is called when *this is an rvalue. If some of the bound
  60. // arguments are stored by value or rvalue reference, we move them.
  61. return functional_internal::Apply<R>(std::move(bound_args_), Idx(),
  62. std::forward<FreeArgs>(free_args)...);
  63. }
  64. template <class... FreeArgs,
  65. class R = base_internal::invoke_result_t<
  66. const F&&, const BoundArgs&&..., FreeArgs&&...>>
  67. R operator()(FreeArgs&&... free_args) const&& {
  68. // This overload is called when *this is an rvalue. If some of the bound
  69. // arguments are stored by value or rvalue reference, we move them.
  70. return functional_internal::Apply<R>(std::move(bound_args_), Idx(),
  71. std::forward<FreeArgs>(free_args)...);
  72. }
  73. };
  74. template <class F, class... BoundArgs>
  75. using bind_front_t = FrontBinder<decay_t<F>, y_absl::decay_t<BoundArgs>...>;
  76. } // namespace functional_internal
  77. Y_ABSL_NAMESPACE_END
  78. } // namespace y_absl
  79. #endif // Y_ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_