1 /*! 2 @file 3 Defines `boost::hana::for_each`. 4 5 @copyright Louis Dionne 2013-2017 6 Distributed under the Boost Software License, Version 1.0. 7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 8 */ 9 10 #ifndef BOOST_HANA_FOR_EACH_HPP 11 #define BOOST_HANA_FOR_EACH_HPP 12 13 #include <boost/hana/fwd/for_each.hpp> 14 15 #include <boost/hana/concept/foldable.hpp> 16 #include <boost/hana/config.hpp> 17 #include <boost/hana/core/dispatch.hpp> 18 #include <boost/hana/unpack.hpp> 19 20 21 BOOST_HANA_NAMESPACE_BEGIN 22 //! @cond 23 template <typename Xs, typename F> operator ()(Xs && xs,F && f) const24 constexpr void for_each_t::operator()(Xs&& xs, F&& f) const { 25 using S = typename hana::tag_of<Xs>::type; 26 using ForEach = BOOST_HANA_DISPATCH_IF(for_each_impl<S>, 27 hana::Foldable<S>::value 28 ); 29 30 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS 31 static_assert(hana::Foldable<S>::value, 32 "hana::for_each(xs, f) requires 'xs' to be Foldable"); 33 #endif 34 35 return ForEach::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f)); 36 } 37 //! @endcond 38 39 namespace detail { 40 template <typename F> 41 struct on_each { 42 F f; 43 template <typename ...Xs> operator ()detail::on_each44 constexpr void operator()(Xs&& ...xs) const { 45 using Swallow = int[]; 46 (void)Swallow{0, ((void)(*f)(static_cast<Xs&&>(xs)), 0)...}; 47 } 48 }; 49 } 50 51 template <typename T, bool condition> 52 struct for_each_impl<T, when<condition>> : default_ { 53 template <typename Xs, typename F> applyfor_each_impl54 static constexpr void apply(Xs&& xs, F&& f) { 55 // We use a pointer instead of a reference to avoid a Clang ICE. 56 hana::unpack(static_cast<Xs&&>(xs), 57 detail::on_each<decltype(&f)>{&f}); 58 } 59 }; 60 BOOST_HANA_NAMESPACE_END 61 62 #endif // !BOOST_HANA_FOR_EACH_HPP 63