/* Copyright 2024 Joaquin M Lopez Munoz. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * See http://www.boost.org/libs/poly_collection for library home page. */ #ifndef BOOST_POLY_COLLECTION_DETAIL_VARIANT_MODEL_HPP #define BOOST_POLY_COLLECTION_DETAIL_VARIANT_MODEL_HPP #if defined(_MSC_VER) #pragma once #endif #if defined(_MSC_VER) #pragma once #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(BOOST_NO_CXX17_HDR_VARIANT) #include #endif namespace boost{namespace variant2{ template class variant; }} /* namespace boost::variant2 */ namespace boost_poly_collection_invoke_visit_variant2{ /* defined here to avoid ADL ambiguities with visit */ template auto invoke_visit(F&& f,const boost::variant2::variant&x)-> decltype(visit(std::forward(f),x)) { return visit(std::forward(f),x); } } /* namespace boost_poly_collection_invoke_visit_variant2 */ namespace boost{ namespace poly_collection{ namespace detail{ /* model for variant_collection */ template struct variant_model; template struct variant_model_is_subvariant:std::false_type{}; template< typename TL1,typename TL2, typename TS1=mp11::mp_set_union,TL1>, typename TS2=mp11::mp_set_union,TL2> > struct variant_model_is_subset:std::integral_constant< bool, mp11::mp_size>::value== mp11::mp_size::value >{}; template struct variant_model_is_subvariant< fixed_variant_impl::fixed_variant, Ts... >:variant_model_is_subset,mp11::mp_list>{}; template struct variant_model_is_subvariant< variant2::variant, Ts... >:variant_model_is_subset,mp11::mp_list>{}; #if !defined(BOOST_NO_CXX17_HDR_VARIANT) template struct variant_model_is_subvariant< std::variant, Ts... >:variant_model_is_subset,mp11::mp_list>{}; #endif template auto invoke_visit(F&& f,const fixed_variant_impl::fixed_variant&x)-> decltype(boost::poly_collection::visit(std::forward(f),x)) { return boost::poly_collection::visit(std::forward(f),x); } using boost_poly_collection_invoke_visit_variant2::invoke_visit; #if !defined(BOOST_NO_CXX17_HDR_VARIANT) template auto invoke_visit(F&& f,const std::variant&x)-> decltype(std::visit(std::forward(f),x)) { return std::visit(std::forward(f),x); } #endif template struct variant_model { using value_type=fixed_variant_impl::fixed_variant; using type_index=std::size_t; using acceptable_type_list=mp11::mp_list; template struct is_terminal: /* using makes VS2015 choke, hence we derive */ mp11::mp_contains{}; template struct is_implementation:std::integral_constant< /* idem */ bool, is_terminal::value|| variant_model_is_subvariant::value >{}; private: template using enable_if_terminal= typename std::enable_if::value>::type*; template using enable_if_not_terminal= typename std::enable_if::value>::type*; public: template static type_index index() { return mp11::mp_find::value; } template =nullptr> static type_index subindex(const T&){return index();} private: template struct subindex_lambda { template std::size_t operator()(I)const { return mp11::mp_find< acceptable_type_list,mp11::mp_at,I>>::value; } }; public: template< template class V,typename... Qs, enable_if_not_terminal> =nullptr> static type_index subindex(const V& x) { static constexpr auto not_found=mp11::mp_size::value; auto i=x.index(); if(i>=sizeof...(Qs))return not_found; else return mp11::mp_with_index( i,subindex_lambda{}); } template =nullptr> static void* subaddress(T& x){return boost::addressof(x);} template =nullptr> static const void* subaddress(const T& x){return boost::addressof(x);} template =nullptr> static void* subaddress(T& x) { return const_cast(subaddress(const_cast(x))); } private: struct subaddress_visitor { template const void* operator()(const T& x)const { return static_cast(boost::addressof(x)); } }; public: template =nullptr> static const void* subaddress(const T& x) { return invoke_visit(subaddress_visitor{},x); } template =nullptr> static const std::type_info& subtype_info(const T& x) { return typeid(x); } private: struct subtype_info_visitor { template const std::type_info& operator()(const T&)const{return typeid(T);} }; public: template =nullptr> static const std::type_info& subtype_info(const T& x) { return invoke_visit(subtype_info_visitor{},x); } using base_iterator=fixed_variant_iterator; using const_base_iterator=fixed_variant_iterator; using base_sentinel=value_type*; using const_base_sentinel=const value_type*; template using iterator=fixed_variant_alternative_iterator; template using const_iterator=fixed_variant_alternative_iterator; template using segment_backend=detail::segment_backend; template using segment_backend_implementation= packed_segment; static base_iterator nonconst_iterator(const_base_iterator it) { return base_iterator{ const_cast(static_cast(it)),it.stride()}; } template static iterator nonconst_iterator(const_iterator it) { return {const_cast(static_cast(it))}; } private: template friend class packed_segment; template using final_type=fixed_variant_impl::fixed_variant_closure< T,fixed_variant_impl::fixed_variant>; template static const value_type* value_ptr(const T* p)noexcept { return reinterpret_cast*>(p); } }; } /* namespace poly_collection::detail */ } /* namespace poly_collection */ } /* namespace boost */ #endif