for_each.hpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /*!
  2. @file
  3. Defines `boost::hana::for_each`.
  4. Copyright Louis Dionne 2013-2022
  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_FOR_EACH_HPP
  9. #define BOOST_HANA_FOR_EACH_HPP
  10. #include <boost/hana/fwd/for_each.hpp>
  11. #include <boost/hana/concept/foldable.hpp>
  12. #include <boost/hana/config.hpp>
  13. #include <boost/hana/core/dispatch.hpp>
  14. #include <boost/hana/unpack.hpp>
  15. namespace boost { namespace hana {
  16. //! @cond
  17. template <typename Xs, typename F>
  18. constexpr void for_each_t::operator()(Xs&& xs, F&& f) const {
  19. using S = typename hana::tag_of<Xs>::type;
  20. using ForEach = BOOST_HANA_DISPATCH_IF(for_each_impl<S>,
  21. hana::Foldable<S>::value
  22. );
  23. #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
  24. static_assert(hana::Foldable<S>::value,
  25. "hana::for_each(xs, f) requires 'xs' to be Foldable");
  26. #endif
  27. return ForEach::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
  28. }
  29. //! @endcond
  30. namespace detail {
  31. template <typename F>
  32. struct on_each {
  33. F f;
  34. template <typename ...Xs>
  35. constexpr void operator()(Xs&& ...xs) const {
  36. using Swallow = int[];
  37. (void)Swallow{0, ((void)(*f)(static_cast<Xs&&>(xs)), 0)...};
  38. }
  39. };
  40. }
  41. template <typename T, bool condition>
  42. struct for_each_impl<T, when<condition>> : default_ {
  43. template <typename Xs, typename F>
  44. static constexpr void apply(Xs&& xs, F&& f) {
  45. // We use a pointer instead of a reference to avoid a Clang ICE.
  46. hana::unpack(static_cast<Xs&&>(xs),
  47. detail::on_each<decltype(&f)>{&f});
  48. }
  49. };
  50. }} // end namespace boost::hana
  51. #endif // !BOOST_HANA_FOR_EACH_HPP