/*************************************************************************** * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * Copyright (c) QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XTL_XVARIANT_HPP #define XTL_XVARIANT_HPP #include "xvariant_impl.hpp" #include "xclosure.hpp" #include "xmeta_utils.hpp" namespace xtl { using mpark::variant; using mpark::monostate; using mpark::bad_variant_access; using mpark::variant_size; #ifdef MPARK_VARIABLE_TEMPLATES using mpark::variant_size_v; #endif using mpark::variant_alternative; using mpark::variant_alternative_t; using mpark::variant_npos; using mpark::visit; using mpark::holds_alternative; using mpark::get; using mpark::get_if; namespace detail { template struct xgetter { template static constexpr T& get(xtl::variant& v) { return xtl::get(v); } template static constexpr T&& get(xtl::variant&& v) { return xtl::get(std::move(v)); } template static constexpr const T& get(const xtl::variant& v) { return xtl::get(v); } template static constexpr const T&& get(const xtl::variant&& v) { return xtl::get(std::move(v)); } }; template struct xgetter { template static constexpr T& get(xtl::variant& v) { return xtl::get>(v).get(); } template static constexpr T& get(xtl::variant&& v) { return xtl::get>(std::move(v)).get(); } template static constexpr const T& get(const xtl::variant& v) { return xtl::get>(v).get(); } template static constexpr const T& get(const xtl::variant&& v) { return xtl::get>(std::move(v)).get(); } }; template struct xgetter { template static constexpr const T& get(const xtl::variant& v) { using cl_type = xtl::xclosure_wrapper; return get_impl(v, xtl::mpl::contains, cl_type>()); } template static constexpr const T& get(const xtl::variant&& v) { using cl_type = xtl::xclosure_wrapper; return get_impl(std::move(v), xtl::mpl::contains, cl_type>()); } template static constexpr const T& get(xtl::variant& v) { return get(static_cast&>(v)); } template static constexpr const T& get(xtl::variant&& v) { return get(static_cast&&>(v)); } private: template static constexpr const T& get_impl(const xtl::variant& v, xtl::mpl::bool_) { return xtl::get>(v).get(); } template static constexpr const T& get_impl(const xtl::variant& v, xtl::mpl::bool_) { return static_cast&>(xtl::get>(v)).get(); } template static constexpr const T& get_impl(const xtl::variant&& v, xtl::mpl::bool_) { return xtl::get>(std::move(v)).get(); } template static constexpr const T& get_impl(const xtl::variant&& v, xtl::mpl::bool_) { return static_cast&&>(xtl::get>(std::move(v))).get(); } }; } template constexpr decltype(auto) xget(xtl::variant& v) { return detail::xgetter::get(v); } template constexpr decltype(auto) xget(xtl::variant&& v) { return detail::xgetter::get(std::move(v)); } template constexpr decltype(auto) xget(const xtl::variant& v) { return detail::xgetter::get(v); } template constexpr decltype(auto) xget(const xtl::variant&& v) { return detail::xgetter::get(std::move(v)); } /************************ * overload for lambdas * ************************/ // This hierarchy is required since ellipsis in using declarations are not supported until C++17 template struct overloaded; template struct overloaded : T { overloaded(T arg) : T(arg) {} using T::operator(); }; template struct overloaded : T1, overloaded { template overloaded(T1 t1, T2 t2, Us... args) : T1(t1), overloaded(t2, args...) {} using T1::operator(); using overloaded::operator(); }; template inline overloaded make_overload(Ts... arg) { return overloaded{arg...}; } } #endif