drop_front_exactly.hpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*!
  2. @file
  3. Defines `boost::hana::drop_front_exactly`.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_DROP_FRONT_EXACTLY_HPP
  9. #define BOOST_HANA_DROP_FRONT_EXACTLY_HPP
  10. #include <boost/hana/fwd/drop_front_exactly.hpp>
  11. #include <boost/hana/bool.hpp>
  12. #include <boost/hana/concept/integral_constant.hpp>
  13. #include <boost/hana/concept/iterable.hpp>
  14. #include <boost/hana/config.hpp>
  15. #include <boost/hana/core/dispatch.hpp>
  16. #include <boost/hana/drop_front.hpp>
  17. #include <boost/hana/integral_constant.hpp>
  18. #include <boost/hana/is_empty.hpp>
  19. BOOST_HANA_NAMESPACE_BEGIN
  20. //! @cond
  21. template <typename Xs, typename N>
  22. constexpr auto drop_front_exactly_t::operator()(Xs&& xs, N const& n) const {
  23. using It = typename hana::tag_of<Xs>::type;
  24. using DropFrontExactly = BOOST_HANA_DISPATCH_IF(drop_front_exactly_impl<It>,
  25. hana::Iterable<It>::value &&
  26. hana::IntegralConstant<N>::value
  27. );
  28. #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
  29. static_assert(hana::Iterable<It>::value,
  30. "hana::drop_front_exactly(xs, n) requires 'xs' to be an Iterable");
  31. static_assert(hana::IntegralConstant<N>::value,
  32. "hana::drop_front_exactly(xs, n) requires 'n' to be an IntegralConstant");
  33. #endif
  34. static_assert(N::value >= 0,
  35. "hana::drop_front_exactly(xs, n) requires 'n' to be non-negative");
  36. return DropFrontExactly::apply(static_cast<Xs&&>(xs), n);
  37. }
  38. template <typename Xs>
  39. constexpr auto drop_front_exactly_t::operator()(Xs&& xs) const {
  40. return (*this)(static_cast<Xs&&>(xs), hana::size_c<1>);
  41. }
  42. //! @endcond
  43. namespace detail {
  44. template <typename Xs, typename N>
  45. constexpr void check_dfe_overflow(Xs const& xs, N const&, hana::true_) {
  46. constexpr bool n_overflew_length = decltype(
  47. hana::is_empty(hana::drop_front(xs, hana::size_c<N::value - 1>))
  48. )::value;
  49. static_assert(!n_overflew_length,
  50. "hana::drop_front_exactly(xs, n) requires 'n' to be less than or "
  51. "equal to the number of elements in 'xs'");
  52. }
  53. template <typename Xs, typename N>
  54. constexpr void check_dfe_overflow(Xs const&, N const&, hana::false_) { }
  55. }
  56. template <typename It, bool condition>
  57. struct drop_front_exactly_impl<It, when<condition>> : default_ {
  58. template <typename Xs, typename N>
  59. static constexpr auto apply(Xs&& xs, N const& n) {
  60. auto result = hana::drop_front(static_cast<Xs&&>(xs), n);
  61. constexpr bool check_for_overflow =
  62. decltype(hana::is_empty(result))::value && N::value != 0;
  63. detail::check_dfe_overflow(xs, n, hana::bool_c<check_for_overflow>);
  64. return result; // NRVO applied
  65. }
  66. };
  67. BOOST_HANA_NAMESPACE_END
  68. #endif // !BOOST_HANA_DROP_FRONT_EXACTLY_HPP