You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
4.2KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_ACTION_PUSH_FRONT_HPP
  14. #define RANGES_V3_ACTION_PUSH_FRONT_HPP
  15. #include <utility>
  16. #include <meta/meta.hpp>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/action/action.hpp>
  19. #include <range/v3/action/insert.hpp>
  20. #include <range/v3/detail/with_braced_init_args.hpp>
  21. #include <range/v3/functional/bind_back.hpp>
  22. #include <range/v3/utility/static_const.hpp>
  23. namespace ranges
  24. {
  25. /// \cond
  26. namespace adl_push_front_detail
  27. {
  28. template<typename Cont, typename T>
  29. using push_front_t = decltype(static_cast<void>(
  30. unwrap_reference(std::declval<Cont &>()).push_front(std::declval<T>())));
  31. template<typename Cont, typename Rng>
  32. using insert_t = decltype(static_cast<void>(
  33. ranges::insert(std::declval<Cont &>(), std::declval<iterator_t<Cont>>(),
  34. std::declval<Rng>())));
  35. template<typename Cont, typename T>
  36. auto push_front(Cont && cont, T && t) -> CPP_ret(push_front_t<Cont, T>)( //
  37. requires lvalue_container_like<Cont> &&
  38. (!range<T>)&&constructible_from<range_value_t<Cont>, T>)
  39. {
  40. unwrap_reference(cont).push_front(static_cast<T &&>(t));
  41. }
  42. template<typename Cont, typename Rng>
  43. auto push_front(Cont && cont, Rng && rng) -> CPP_ret(insert_t<Cont, Rng>)( //
  44. requires lvalue_container_like<Cont> && range<Rng>)
  45. {
  46. ranges::insert(cont, begin(cont), static_cast<Rng &&>(rng));
  47. }
  48. // clang-format off
  49. CPP_def
  50. (
  51. template(typename Rng, typename T)
  52. concept can_push_front_,
  53. requires (Rng &&rng, T &&t)
  54. (
  55. push_front(rng, (T &&) t)
  56. )
  57. );
  58. // clang-format on
  59. struct push_front_fn
  60. {
  61. private:
  62. friend actions::action_access;
  63. template<typename T>
  64. static auto bind(push_front_fn push_front, T && val)
  65. {
  66. return bind_back(push_front, static_cast<T &&>(val));
  67. }
  68. #ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA
  69. template<typename T, std::size_t N>
  70. struct lamduh
  71. {
  72. T (&val_)[N];
  73. template<typename Rng>
  74. auto operator()(Rng && rng) const
  75. -> invoke_result_t<push_front_fn, Rng, T (&)[N]>
  76. {
  77. return push_front_fn{}(static_cast<Rng &&>(rng), val_);
  78. }
  79. };
  80. template<typename T, std::size_t N>
  81. static lamduh<T, N> bind(push_front_fn, T (&val)[N])
  82. {
  83. return {val};
  84. }
  85. #else // ^^^ workaround / no workaround vvv
  86. template<typename T, std::size_t N>
  87. static auto bind(push_front_fn, T (&val)[N])
  88. {
  89. return [&val](auto && rng)
  90. -> invoke_result_t<push_front_fn, decltype(rng), T(&)[N]>
  91. {
  92. return push_front_fn{}(static_cast<decltype(rng)>(rng), val);
  93. };
  94. }
  95. #endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA
  96. public:
  97. template<typename Rng, typename T>
  98. auto operator()(Rng && rng, T && t) const -> CPP_ret(Rng)( //
  99. requires input_range<Rng> && can_push_front_<Rng, T> &&
  100. (range<T> || constructible_from<range_value_t<Rng>, T>))
  101. {
  102. push_front(rng, static_cast<T &&>(t));
  103. return static_cast<Rng &&>(rng);
  104. }
  105. };
  106. } // namespace adl_push_front_detail
  107. /// \endcond
  108. namespace actions
  109. {
  110. /// \ingroup group-actions
  111. RANGES_INLINE_VARIABLE(
  112. detail::with_braced_init_args<action<adl_push_front_detail::push_front_fn>>,
  113. push_front)
  114. } // namespace actions
  115. using actions::push_front;
  116. } // namespace ranges
  117. #endif