File indexing completed on 2025-01-30 09:43:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_HANA_OPTIONAL_HPP
0011 #define BOOST_HANA_OPTIONAL_HPP
0012
0013 #include <boost/hana/fwd/optional.hpp>
0014
0015 #include <boost/hana/bool.hpp>
0016 #include <boost/hana/config.hpp>
0017 #include <boost/hana/core/tag_of.hpp>
0018 #include <boost/hana/detail/decay.hpp>
0019 #include <boost/hana/detail/operators/adl.hpp>
0020 #include <boost/hana/detail/operators/comparable.hpp>
0021 #include <boost/hana/detail/operators/monad.hpp>
0022 #include <boost/hana/detail/operators/orderable.hpp>
0023 #include <boost/hana/detail/wrong.hpp>
0024 #include <boost/hana/functional/partial.hpp>
0025 #include <boost/hana/fwd/any_of.hpp>
0026 #include <boost/hana/fwd/ap.hpp>
0027 #include <boost/hana/fwd/concat.hpp>
0028 #include <boost/hana/fwd/core/make.hpp>
0029 #include <boost/hana/fwd/empty.hpp>
0030 #include <boost/hana/fwd/equal.hpp>
0031 #include <boost/hana/fwd/find_if.hpp>
0032 #include <boost/hana/fwd/flatten.hpp>
0033 #include <boost/hana/fwd/less.hpp>
0034 #include <boost/hana/fwd/lift.hpp>
0035 #include <boost/hana/fwd/transform.hpp>
0036 #include <boost/hana/fwd/type.hpp>
0037 #include <boost/hana/fwd/unpack.hpp>
0038
0039 #include <cstddef> // std::nullptr_t
0040 #include <type_traits>
0041 #include <utility>
0042
0043
0044 namespace boost { namespace hana {
0045
0046
0047
0048 namespace detail {
0049 template <typename T, typename = typename hana::tag_of<T>::type>
0050 struct nested_type { };
0051
0052 template <typename T>
0053 struct nested_type<T, type_tag> { using type = typename T::type; };
0054 }
0055
0056 template <typename T>
0057 struct optional<T> : detail::operators::adl<>, detail::nested_type<T> {
0058
0059 constexpr optional() = default;
0060 constexpr optional(optional const&) = default;
0061 constexpr optional(optional&&) = default;
0062
0063 constexpr optional(T const& t)
0064 : value_(t)
0065 { }
0066
0067 constexpr optional(T&& t)
0068 : value_(static_cast<T&&>(t))
0069 { }
0070
0071
0072 constexpr optional& operator=(optional const&) = default;
0073 constexpr optional& operator=(optional&&) = default;
0074
0075
0076 constexpr T const* operator->() const { return &value_; }
0077 constexpr T* operator->() { return &value_; }
0078
0079 constexpr T& value() & { return value_; }
0080 constexpr T const& value() const& { return value_; }
0081 constexpr T&& value() && { return static_cast<T&&>(value_); }
0082 constexpr T const&& value() const&& { return static_cast<T const&&>(value_); }
0083
0084 constexpr T& operator*() & { return value_; }
0085 constexpr T const& operator*() const& { return value_; }
0086 constexpr T&& operator*() && { return static_cast<T&&>(value_); }
0087 constexpr T const&& operator*() const&& { return static_cast<T const&&>(value_); }
0088
0089 template <typename U> constexpr T& value_or(U&&) & { return value_; }
0090 template <typename U> constexpr T const& value_or(U&&) const& { return value_; }
0091 template <typename U> constexpr T&& value_or(U&&) && { return static_cast<T&&>(value_); }
0092 template <typename U> constexpr T const&& value_or(U&&) const&& { return static_cast<T const&&>(value_); }
0093
0094
0095
0096 T value_;
0097 };
0098
0099
0100 template <typename ...dummy>
0101 constexpr auto optional<>::value() const {
0102 static_assert(detail::wrong<dummy...>{},
0103 "hana::optional::value() requires a non-empty optional");
0104 }
0105
0106 template <typename ...dummy>
0107 constexpr auto optional<>::operator*() const {
0108 static_assert(detail::wrong<dummy...>{},
0109 "hana::optional::operator* requires a non-empty optional");
0110 }
0111
0112 template <typename U>
0113 constexpr U&& optional<>::value_or(U&& u) const {
0114 return static_cast<U&&>(u);
0115 }
0116
0117 template <typename T>
0118 constexpr auto make_just_t::operator()(T&& t) const {
0119 return hana::optional<typename detail::decay<T>::type>(static_cast<T&&>(t));
0120 }
0121
0122
0123 template <typename ...T>
0124 struct tag_of<optional<T...>> {
0125 using type = optional_tag;
0126 };
0127
0128
0129
0130
0131 template <>
0132 struct make_impl<optional_tag> {
0133 template <typename X>
0134 static constexpr auto apply(X&& x)
0135 { return hana::just(static_cast<X&&>(x)); }
0136
0137 static constexpr auto apply()
0138 { return hana::nothing; }
0139 };
0140
0141
0142
0143
0144 namespace detail {
0145 template <>
0146 struct comparable_operators<optional_tag> {
0147 static constexpr bool value = true;
0148 };
0149 template <>
0150 struct orderable_operators<optional_tag> {
0151 static constexpr bool value = true;
0152 };
0153 template <>
0154 struct monad_operators<optional_tag> {
0155 static constexpr bool value = true;
0156 };
0157 }
0158
0159
0160
0161
0162
0163 template <typename ...T>
0164 constexpr auto is_just_t::operator()(optional<T...> const&) const
0165 { return hana::bool_c<sizeof...(T) != 0>; }
0166
0167 template <typename ...T>
0168 constexpr auto is_nothing_t::operator()(optional<T...> const&) const
0169 { return hana::bool_c<sizeof...(T) == 0>; }
0170
0171
0172
0173
0174
0175 namespace detail {
0176 struct sfinae_impl {
0177 template <typename F, typename ...X, typename = decltype(
0178 std::declval<F>()(std::declval<X>()...)
0179 )>
0180 constexpr decltype(auto) operator()(int, F&& f, X&& ...x) const {
0181 using Return = decltype(static_cast<F&&>(f)(static_cast<X&&>(x)...));
0182 static_assert(!std::is_same<Return, void>::value,
0183 "hana::sfinae(f)(args...) requires f(args...) to be non-void");
0184
0185 return hana::just(static_cast<F&&>(f)(static_cast<X&&>(x)...));
0186 }
0187
0188 template <typename F, typename ...X>
0189 constexpr auto operator()(long, F&&, X&& ...) const
0190 { return hana::nothing; }
0191 };
0192 }
0193
0194
0195 template <typename F>
0196 constexpr decltype(auto) sfinae_t::operator()(F&& f) const {
0197 return hana::partial(detail::sfinae_impl{}, int{},
0198 static_cast<F&&>(f));
0199 }
0200
0201
0202
0203
0204
0205 template <>
0206 struct equal_impl<optional_tag, optional_tag> {
0207 template <typename T, typename U>
0208 static constexpr auto apply(hana::optional<T> const& t, hana::optional<U> const& u)
0209 { return hana::equal(t.value_, u.value_); }
0210
0211 static constexpr hana::true_ apply(hana::optional<> const&, hana::optional<> const&)
0212 { return {}; }
0213
0214 template <typename T, typename U>
0215 static constexpr hana::false_ apply(T const&, U const&)
0216 { return {}; }
0217 };
0218
0219
0220
0221
0222 template <>
0223 struct less_impl<optional_tag, optional_tag> {
0224 template <typename T>
0225 static constexpr hana::true_ apply(hana::optional<> const&, hana::optional<T> const&)
0226 { return {}; }
0227
0228 static constexpr hana::false_ apply(hana::optional<> const&, hana::optional<> const&)
0229 { return {}; }
0230
0231 template <typename T>
0232 static constexpr hana::false_ apply(hana::optional<T> const&, hana::optional<> const&)
0233 { return {}; }
0234
0235 template <typename T, typename U>
0236 static constexpr auto apply(hana::optional<T> const& x, hana::optional<U> const& y)
0237 { return hana::less(x.value_, y.value_); }
0238 };
0239
0240
0241
0242
0243 template <>
0244 struct transform_impl<optional_tag> {
0245 template <typename F>
0246 static constexpr auto apply(optional<> const&, F&&)
0247 { return hana::nothing; }
0248
0249 template <typename T, typename F>
0250 static constexpr auto apply(optional<T> const& opt, F&& f)
0251 { return hana::just(static_cast<F&&>(f)(opt.value_)); }
0252
0253 template <typename T, typename F>
0254 static constexpr auto apply(optional<T>& opt, F&& f)
0255 { return hana::just(static_cast<F&&>(f)(opt.value_)); }
0256
0257 template <typename T, typename F>
0258 static constexpr auto apply(optional<T>&& opt, F&& f)
0259 { return hana::just(static_cast<F&&>(f)(static_cast<T&&>(opt.value_))); }
0260 };
0261
0262
0263
0264
0265 template <>
0266 struct lift_impl<optional_tag> {
0267 template <typename X>
0268 static constexpr auto apply(X&& x)
0269 { return hana::just(static_cast<X&&>(x)); }
0270 };
0271
0272 template <>
0273 struct ap_impl<optional_tag> {
0274 template <typename F, typename X>
0275 static constexpr auto ap_helper(F&&, X&&, ...)
0276 { return hana::nothing; }
0277
0278 template <typename F, typename X>
0279 static constexpr auto ap_helper(F&& f, X&& x, hana::true_, hana::true_)
0280 { return hana::just(static_cast<F&&>(f).value_(static_cast<X&&>(x).value_)); }
0281
0282 template <typename F, typename X>
0283 static constexpr auto apply(F&& f, X&& x) {
0284 return ap_impl::ap_helper(static_cast<F&&>(f), static_cast<X&&>(x),
0285 hana::is_just(f), hana::is_just(x));
0286 }
0287 };
0288
0289
0290
0291
0292 template <>
0293 struct flatten_impl<optional_tag> {
0294 static constexpr auto apply(optional<> const&)
0295 { return hana::nothing; }
0296
0297 static constexpr auto apply(optional<optional<>> const&)
0298 { return hana::nothing; }
0299
0300 template <typename T>
0301 static constexpr auto apply(optional<optional<T>> const& opt)
0302 { return hana::just(opt.value_.value_); }
0303
0304 template <typename T>
0305 static constexpr auto apply(optional<optional<T>>&& opt)
0306 { return hana::just(static_cast<T&&>(opt.value_.value_)); }
0307 };
0308
0309
0310
0311
0312 template <>
0313 struct concat_impl<optional_tag> {
0314 template <typename Y>
0315 static constexpr auto apply(hana::optional<>&, Y&& y)
0316 { return static_cast<Y&&>(y); }
0317
0318 template <typename Y>
0319 static constexpr auto apply(hana::optional<>&&, Y&& y)
0320 { return static_cast<Y&&>(y); }
0321
0322 template <typename Y>
0323 static constexpr auto apply(hana::optional<> const&, Y&& y)
0324 { return static_cast<Y&&>(y); }
0325
0326 template <typename X, typename Y>
0327 static constexpr auto apply(X&& x, Y&&)
0328 { return static_cast<X&&>(x); }
0329 };
0330
0331 template <>
0332 struct empty_impl<optional_tag> {
0333 static constexpr auto apply()
0334 { return hana::nothing; }
0335 };
0336
0337
0338
0339
0340 template <>
0341 struct unpack_impl<optional_tag> {
0342 template <typename T, typename F>
0343 static constexpr decltype(auto) apply(optional<T>&& opt, F&& f)
0344 { return static_cast<F&&>(f)(static_cast<T&&>(opt.value_)); }
0345
0346 template <typename T, typename F>
0347 static constexpr decltype(auto) apply(optional<T> const& opt, F&& f)
0348 { return static_cast<F&&>(f)(opt.value_); }
0349
0350 template <typename T, typename F>
0351 static constexpr decltype(auto) apply(optional<T>& opt, F&& f)
0352 { return static_cast<F&&>(f)(opt.value_); }
0353
0354 template <typename F>
0355 static constexpr decltype(auto) apply(optional<> const&, F&& f)
0356 { return static_cast<F&&>(f)(); }
0357 };
0358
0359
0360
0361
0362 namespace detail {
0363 template <bool>
0364 struct optional_find_if {
0365 template <typename T>
0366 static constexpr auto apply(T const&)
0367 { return hana::nothing; }
0368 };
0369
0370 template <>
0371 struct optional_find_if<true> {
0372 template <typename T>
0373 static constexpr auto apply(T&& t)
0374 { return hana::just(static_cast<T&&>(t)); }
0375 };
0376 }
0377
0378 template <>
0379 struct find_if_impl<optional_tag> {
0380 template <typename T, typename Pred>
0381 static constexpr auto apply(hana::optional<T> const& opt, Pred&& pred) {
0382 constexpr bool found = decltype(static_cast<Pred&&>(pred)(opt.value_))::value;
0383 return detail::optional_find_if<found>::apply(opt.value_);
0384 }
0385
0386 template <typename T, typename Pred>
0387 static constexpr auto apply(hana::optional<T>& opt, Pred&& pred) {
0388 constexpr bool found = decltype(static_cast<Pred&&>(pred)(opt.value_))::value;
0389 return detail::optional_find_if<found>::apply(opt.value_);
0390 }
0391
0392 template <typename T, typename Pred>
0393 static constexpr auto apply(hana::optional<T>&& opt, Pred&& pred) {
0394 constexpr bool found = decltype(
0395 static_cast<Pred&&>(pred)(static_cast<T&&>(opt.value_))
0396 )::value;
0397 return detail::optional_find_if<found>::apply(static_cast<T&&>(opt.value_));
0398 }
0399
0400 template <typename Pred>
0401 static constexpr auto apply(hana::optional<> const&, Pred&&)
0402 { return hana::nothing; }
0403 };
0404
0405 template <>
0406 struct any_of_impl<optional_tag> {
0407 template <typename T, typename Pred>
0408 static constexpr auto apply(hana::optional<T> const& opt, Pred&& pred)
0409 { return static_cast<Pred&&>(pred)(opt.value_); }
0410
0411 template <typename Pred>
0412 static constexpr hana::false_ apply(hana::optional<> const&, Pred&&)
0413 { return {}; }
0414 };
0415 }}
0416
0417 #endif