Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:38

0001 /*!
0002 @file
0003 Defines `boost::hana::optional`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
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     // optional<>
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         // 5.3.1, Constructors
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         // 5.3.3, Assignment
0072         constexpr optional& operator=(optional const&) = default;
0073         constexpr optional& operator=(optional&&) = default;
0074 
0075         // 5.3.5, Observers
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         // We leave this public because it simplifies the implementation, but
0095         // this should be considered private by users.
0096         T value_;
0097     };
0098 
0099     //! @cond
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     //! @endcond
0122 
0123     template <typename ...T>
0124     struct tag_of<optional<T...>> {
0125         using type = optional_tag;
0126     };
0127 
0128     //////////////////////////////////////////////////////////////////////////
0129     // make<optional_tag>
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     // Operators
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     // is_just and is_nothing
0161     //////////////////////////////////////////////////////////////////////////
0162     //! @cond
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     //! @endcond
0171 
0172     //////////////////////////////////////////////////////////////////////////
0173     // sfinae
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     //! @cond
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     //! @endcond
0201 
0202     //////////////////////////////////////////////////////////////////////////
0203     // Comparable
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     // Orderable
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     // Functor
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     // Applicative
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     // Monad
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     // MonadPlus
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     // Foldable
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     // Searchable
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 }} // end namespace boost::hana
0416 
0417 #endif // !BOOST_HANA_OPTIONAL_HPP