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.

135 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_BACK_HPP
  14. #define RANGES_V3_ACTION_PUSH_BACK_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_back_detail
  27. {
  28. template<typename Cont, typename T>
  29. using push_back_t = decltype(static_cast<void>(
  30. unwrap_reference(std::declval<Cont &>()).push_back(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<sentinel_t<Cont>>(),
  34. std::declval<Rng>())));
  35. template<typename Cont, typename T>
  36. auto push_back(Cont && cont, T && t) -> CPP_ret(push_back_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_back(static_cast<T &&>(t));
  41. }
  42. template<typename Cont, typename Rng>
  43. auto push_back(Cont && cont, Rng && rng) -> CPP_ret(insert_t<Cont, Rng>)( //
  44. requires lvalue_container_like<Cont> && range<Rng>)
  45. {
  46. ranges::insert(cont, end(cont), static_cast<Rng &&>(rng));
  47. }
  48. /// \cond
  49. // clang-format off
  50. CPP_def
  51. (
  52. template(typename Rng, typename T)
  53. concept can_push_back_,
  54. requires (Rng &&rng, T &&t)
  55. (
  56. push_back(rng, (T &&) t)
  57. )
  58. );
  59. // clang-format on
  60. /// \endcond
  61. struct push_back_fn
  62. {
  63. private:
  64. friend actions::action_access;
  65. template<typename T>
  66. static auto bind(push_back_fn push_back, T && val)
  67. {
  68. return bind_back(push_back, static_cast<T &&>(val));
  69. }
  70. #ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA
  71. template<typename T, std::size_t N>
  72. struct lamduh
  73. {
  74. T (&val_)[N];
  75. template<typename Rng>
  76. auto operator()(Rng && rng) const
  77. -> invoke_result_t<push_back_fn, Rng, T (&)[N]>
  78. {
  79. return push_back_fn{}(static_cast<Rng &&>(rng), val_);
  80. }
  81. };
  82. template<typename T, std::size_t N>
  83. static lamduh<T, N> bind(push_back_fn, T (&val)[N])
  84. {
  85. return {val};
  86. }
  87. #else // ^^^ workaround / no workaround vvv
  88. template<typename T, std::size_t N>
  89. static auto bind(push_back_fn, T (&val)[N])
  90. {
  91. return [&val](auto && rng)
  92. -> invoke_result_t<push_back_fn, decltype(rng), T(&)[N]>
  93. {
  94. return push_back_fn{}(static_cast<decltype(rng)>(rng), val);
  95. };
  96. }
  97. #endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA
  98. public:
  99. template<typename Rng, typename T>
  100. auto operator()(Rng && rng, T && t) const -> CPP_ret(Rng)( //
  101. requires input_range<Rng> && can_push_back_<Rng, T> &&
  102. (range<T> || constructible_from<range_value_t<Rng>, T>))
  103. {
  104. push_back(rng, static_cast<T &&>(t));
  105. return static_cast<Rng &&>(rng);
  106. }
  107. };
  108. } // namespace adl_push_back_detail
  109. /// \endcond
  110. namespace actions
  111. {
  112. /// \ingroup group-actions
  113. RANGES_INLINE_VARIABLE(
  114. detail::with_braced_init_args<action<adl_push_back_detail::push_back_fn>>,
  115. push_back)
  116. } // namespace actions
  117. using actions::push_back;
  118. } // namespace ranges
  119. #endif