// This file is part of Desktop App Toolkit, // a set of libraries for developing nice desktop applications. // // For license and copyright information please follow this link: // https://github.com/desktop-app/legal/blob/master/LEGAL // #pragma once #include "base/match_method.h" #include "base/assertion.h" #include #include namespace v { namespace details { template struct contains; template inline constexpr bool contains_v = contains::value; template struct contains : std::bool_constant< std::is_same_v || contains_v> { }; template struct contains : std::bool_constant { }; } // namespace details using null_t = std::monostate; inline constexpr null_t null{}; namespace type_list = rpl::details::type_list; template struct normalized_variant { using list = type_list::list; using distinct = type_list::distinct_t; using type = std::conditional_t< type_list::size_v == 1, type_list::get_t<0, distinct>, type_list::extract_to_t>; }; template using normalized_variant_t = typename normalized_variant::type; template struct match_helper; template < typename Type, typename ...Types, typename Variant, typename ...Methods> struct match_helper, Variant, Methods...> { static decltype(auto) call(Variant &value, Methods &&...methods) { if (const auto v = std::get_if(&value)) { return base::match_method( *v, std::forward(methods)...); } return match_helper< type_list::list, Variant, Methods...>::call( value, std::forward(methods)...); } }; template < typename Type, typename Variant, typename ...Methods> struct match_helper, Variant, Methods...> { static decltype(auto) call(Variant &value, Methods &&...methods) { if (const auto v = std::get_if(&value)) { return base::match_method( *v, std::forward(methods)...); } Unexpected("Valueless variant in base::match()."); } }; template inline decltype(auto) match( std::variant &value, Methods &&...methods) { return match_helper< type_list::list, std::variant, Methods...>::call(value, std::forward(methods)...); } template inline decltype(auto) match( const std::variant &value, Methods &&...methods) { return match_helper< type_list::list, const std::variant, Methods...>::call(value, std::forward(methods)...); } template [[nodiscard]] inline bool is(const std::variant &value) { return std::holds_alternative(value); } template [[nodiscard]] inline bool is_null( const std::variant &value) { return is(value); } // On macOS std::get is macOS 10.14+ because of the exception type. // So we use our own, implemented using std::get_if. template [[nodiscard]] inline Type &get(std::variant &value) { const auto result = std::get_if(&value); Ensures(result != nullptr); return *result; } template [[nodiscard]] inline const Type &get(const std::variant &value) { const auto result = std::get_if(&value); Ensures(result != nullptr); return *result; } } // namespace v template < typename ...Types, typename Type, typename = std::enable_if_t>> inline bool operator==(const std::variant &a, const Type &b) { return (a == std::variant(b)); } template < typename ...Types, typename Type, typename = std::enable_if_t>> inline bool operator==(const Type &a, const std::variant &b) { return (std::variant(a) == b); } template < typename ...Types, typename Type, typename = std::enable_if_t>> inline bool operator!=(const std::variant &a, const Type &b) { return (a != std::variant(b)); } template < typename ...Types, typename Type, typename = std::enable_if_t>> inline bool operator!=(const Type &a, const std::variant &b) { return (std::variant(a) != b); }