File indexing completed on 2025-01-18 09:38:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_HANA_LAZY_HPP
0011 #define BOOST_HANA_LAZY_HPP
0012
0013 #include <boost/hana/fwd/lazy.hpp>
0014
0015 #include <boost/hana/basic_tuple.hpp>
0016 #include <boost/hana/config.hpp>
0017 #include <boost/hana/core/make.hpp>
0018 #include <boost/hana/detail/decay.hpp>
0019 #include <boost/hana/detail/operators/adl.hpp>
0020 #include <boost/hana/detail/operators/monad.hpp>
0021 #include <boost/hana/functional/apply.hpp>
0022 #include <boost/hana/functional/compose.hpp>
0023 #include <boost/hana/functional/on.hpp>
0024 #include <boost/hana/fwd/ap.hpp>
0025 #include <boost/hana/fwd/duplicate.hpp>
0026 #include <boost/hana/fwd/eval.hpp>
0027 #include <boost/hana/fwd/extend.hpp>
0028 #include <boost/hana/fwd/extract.hpp>
0029 #include <boost/hana/fwd/flatten.hpp>
0030 #include <boost/hana/fwd/lift.hpp>
0031 #include <boost/hana/fwd/transform.hpp>
0032
0033 #include <cstddef>
0034 #include <type_traits>
0035 #include <utility>
0036
0037
0038 namespace boost { namespace hana {
0039
0040
0041
0042 template <typename Indices, typename F, typename ...Args>
0043 struct lazy_apply_t;
0044
0045 namespace detail { struct lazy_secret { }; }
0046
0047 template <std::size_t ...n, typename F, typename ...Args>
0048 struct lazy_apply_t<std::index_sequence<n...>, F, Args...>
0049 : detail::operators::adl<>
0050 {
0051 template <typename ...T>
0052 constexpr lazy_apply_t(detail::lazy_secret, T&& ...t)
0053 : storage_{static_cast<T&&>(t)...}
0054 { }
0055
0056 basic_tuple<F, Args...> storage_;
0057 using hana_tag = lazy_tag;
0058 };
0059
0060 template <typename X>
0061 struct lazy_value_t : detail::operators::adl<> {
0062 template <typename Y>
0063 constexpr lazy_value_t(detail::lazy_secret, Y&& y)
0064 : storage_{static_cast<Y&&>(y)}
0065 { }
0066
0067 basic_tuple<X> storage_;
0068 using hana_tag = lazy_tag;
0069
0070
0071 template <typename ...Args>
0072 constexpr lazy_apply_t<
0073 std::make_index_sequence<sizeof...(Args)>,
0074 X, typename detail::decay<Args>::type...
0075 > operator()(Args&& ...args) const& {
0076 return {detail::lazy_secret{},
0077 hana::at_c<0>(storage_), static_cast<Args&&>(args)...};
0078 }
0079
0080 template <typename ...Args>
0081 constexpr lazy_apply_t<
0082 std::make_index_sequence<sizeof...(Args)>,
0083 X, typename detail::decay<Args>::type...
0084 > operator()(Args&& ...args) && {
0085 return {detail::lazy_secret{},
0086 static_cast<X&&>(hana::at_c<0>(storage_)),
0087 static_cast<Args&&>(args)...
0088 };
0089 }
0090 };
0091
0092
0093
0094
0095 template <>
0096 struct make_impl<lazy_tag> {
0097 template <typename X>
0098 static constexpr lazy_value_t<typename detail::decay<X>::type> apply(X&& x) {
0099 return {detail::lazy_secret{}, static_cast<X&&>(x)};
0100 }
0101 };
0102
0103
0104
0105
0106 namespace detail {
0107 template <>
0108 struct monad_operators<lazy_tag> { static constexpr bool value = true; };
0109 }
0110
0111
0112
0113
0114 template <>
0115 struct eval_impl<lazy_tag> {
0116
0117 template <std::size_t ...n, typename F, typename ...Args>
0118 static constexpr decltype(auto)
0119 apply(lazy_apply_t<std::index_sequence<n...>, F, Args...> const& expr) {
0120 return hana::at_c<0>(expr.storage_)(
0121 hana::at_c<n+1>(expr.storage_)...
0122 );
0123 }
0124
0125 template <std::size_t ...n, typename F, typename ...Args>
0126 static constexpr decltype(auto)
0127 apply(lazy_apply_t<std::index_sequence<n...>, F, Args...>& expr) {
0128 return hana::at_c<0>(expr.storage_)(
0129 hana::at_c<n+1>(expr.storage_)...
0130 );
0131 }
0132
0133 template <std::size_t ...n, typename F, typename ...Args>
0134 static constexpr decltype(auto)
0135 apply(lazy_apply_t<std::index_sequence<n...>, F, Args...>&& expr) {
0136 return static_cast<F&&>(hana::at_c<0>(expr.storage_))(
0137 static_cast<Args&&>(hana::at_c<n+1>(expr.storage_))...
0138 );
0139 }
0140
0141
0142 template <typename X>
0143 static constexpr X const& apply(lazy_value_t<X> const& expr)
0144 { return hana::at_c<0>(expr.storage_); }
0145
0146 template <typename X>
0147 static constexpr X& apply(lazy_value_t<X>& expr)
0148 { return hana::at_c<0>(expr.storage_); }
0149
0150 template <typename X>
0151 static constexpr X apply(lazy_value_t<X>&& expr)
0152 { return static_cast<X&&>(hana::at_c<0>(expr.storage_)); }
0153 };
0154
0155
0156
0157
0158 template <>
0159 struct transform_impl<lazy_tag> {
0160 template <typename Expr, typename F>
0161 static constexpr auto apply(Expr&& expr, F&& f) {
0162 return hana::make_lazy(hana::compose(static_cast<F&&>(f), hana::eval))(
0163 static_cast<Expr&&>(expr)
0164 );
0165 }
0166 };
0167
0168
0169
0170
0171 template <>
0172 struct lift_impl<lazy_tag> {
0173 template <typename X>
0174 static constexpr lazy_value_t<typename detail::decay<X>::type>
0175 apply(X&& x) {
0176 return {detail::lazy_secret{}, static_cast<X&&>(x)};
0177 }
0178 };
0179
0180 template <>
0181 struct ap_impl<lazy_tag> {
0182 template <typename F, typename X>
0183 static constexpr decltype(auto) apply(F&& f, X&& x) {
0184 return hana::make_lazy(hana::on(hana::apply, hana::eval))(
0185 static_cast<F&&>(f), static_cast<X&&>(x)
0186 );
0187 }
0188 };
0189
0190
0191
0192
0193 template <>
0194 struct flatten_impl<lazy_tag> {
0195 template <typename Expr>
0196 static constexpr decltype(auto) apply(Expr&& expr) {
0197 return hana::make_lazy(hana::compose(hana::eval, hana::eval))(
0198 static_cast<Expr&&>(expr)
0199 );
0200 }
0201 };
0202
0203
0204
0205
0206 template <>
0207 struct extract_impl<lazy_tag> {
0208 template <typename Expr>
0209 static constexpr decltype(auto) apply(Expr&& expr)
0210 { return hana::eval(static_cast<Expr&&>(expr)); }
0211 };
0212
0213 template <>
0214 struct duplicate_impl<lazy_tag> {
0215 template <typename Expr>
0216 static constexpr decltype(auto) apply(Expr&& expr)
0217 { return hana::make_lazy(static_cast<Expr&&>(expr)); }
0218 };
0219
0220 template <>
0221 struct extend_impl<lazy_tag> {
0222 template <typename Expr, typename F>
0223 static constexpr decltype(auto) apply(Expr&& expr, F&& f) {
0224 return hana::make_lazy(static_cast<F&&>(f))(static_cast<Expr&&>(expr));
0225 }
0226 };
0227 }}
0228
0229 #endif