Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:45:58

0001 /* Copyright 2024 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/poly_collection for library home page.
0007  */
0008 
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_VARIANT_MODEL_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_VARIANT_MODEL_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #if defined(_MSC_VER)
0017 #pragma once
0018 #endif
0019 
0020 #include <boost/config.hpp>
0021 #include <boost/core/addressof.hpp>
0022 #include <boost/mp11/algorithm.hpp>
0023 #include <boost/mp11/list.hpp>
0024 #include <boost/mp11/set.hpp>
0025 #include <boost/poly_collection/detail/is_acceptable.hpp>
0026 #include <boost/poly_collection/detail/fixed_variant.hpp>
0027 #include <boost/poly_collection/detail/fixed_variant_iterator.hpp>
0028 #include <boost/poly_collection/detail/packed_segment.hpp>
0029 #include <boost/poly_collection/detail/segment_backend.hpp>
0030 #include <memory>
0031 #include <type_traits>
0032 #include <typeinfo>
0033 #include <utility>
0034 
0035 #if !defined(BOOST_NO_CXX17_HDR_VARIANT)
0036 #include <variant>
0037 #endif
0038 
0039 namespace boost{namespace variant2{
0040 
0041 template<class... T> class variant;
0042 
0043 }} /* namespace boost::variant2 */
0044 
0045 namespace boost_poly_collection_invoke_visit_variant2{
0046 
0047 /* defined here to avoid ADL ambiguities with visit */
0048 
0049 template<typename F,typename... Ts>
0050 auto invoke_visit(F&& f,const boost::variant2::variant<Ts...>&x)->
0051   decltype(visit(std::forward<F>(f),x))
0052 {
0053   return visit(std::forward<F>(f),x);
0054 }
0055 
0056 } /* namespace boost_poly_collection_invoke_visit_variant2 */
0057 
0058 namespace boost{
0059 
0060 namespace poly_collection{
0061 
0062 namespace detail{
0063 
0064 /* model for variant_collection */
0065 
0066 template<typename... Ts>
0067 struct variant_model;
0068 
0069 template<typename V,typename...Ts>
0070 struct variant_model_is_subvariant:std::false_type{};
0071 
0072 template<
0073   typename TL1,typename TL2,
0074   typename TS1=mp11::mp_set_union<mp11::mp_list<>,TL1>,
0075   typename TS2=mp11::mp_set_union<mp11::mp_list<>,TL2>
0076 >
0077 struct variant_model_is_subset:std::integral_constant<
0078   bool,
0079   mp11::mp_size<mp11::mp_set_union<TS1,TS2>>::value==
0080   mp11::mp_size<TS2>::value
0081 >{};
0082 
0083 template<typename... Us,typename... Ts>
0084 struct variant_model_is_subvariant<
0085   fixed_variant_impl::fixed_variant<Us...>,
0086   Ts...
0087 >:variant_model_is_subset<mp11::mp_list<Us...>,mp11::mp_list<Ts...>>{};
0088 
0089 template<typename... Us,typename... Ts>
0090 struct variant_model_is_subvariant<
0091   variant2::variant<Us...>,
0092   Ts...
0093 >:variant_model_is_subset<mp11::mp_list<Us...>,mp11::mp_list<Ts...>>{};
0094 
0095 #if !defined(BOOST_NO_CXX17_HDR_VARIANT)
0096 template<typename... Us,typename... Ts>
0097 struct variant_model_is_subvariant<
0098   std::variant<Us...>,
0099   Ts...
0100 >:variant_model_is_subset<mp11::mp_list<Us...>,mp11::mp_list<Ts...>>{};
0101 #endif
0102 
0103 template<typename F,typename... Ts>
0104 auto invoke_visit(F&& f,const fixed_variant_impl::fixed_variant<Ts...>&x)->
0105   decltype(boost::poly_collection::visit(std::forward<F>(f),x))
0106 {
0107   return boost::poly_collection::visit(std::forward<F>(f),x);
0108 }
0109 
0110 using boost_poly_collection_invoke_visit_variant2::invoke_visit;
0111 
0112 #if !defined(BOOST_NO_CXX17_HDR_VARIANT)
0113 template<typename F,typename... Ts>
0114 auto invoke_visit(F&& f,const std::variant<Ts...>&x)->
0115   decltype(std::visit(std::forward<F>(f),x))
0116 {
0117   return std::visit(std::forward<F>(f),x);
0118 }
0119 #endif
0120 
0121 template<typename... Ts>
0122 struct variant_model
0123 {
0124   using value_type=fixed_variant_impl::fixed_variant<Ts...>;
0125   using type_index=std::size_t;
0126   using acceptable_type_list=mp11::mp_list<Ts...>;
0127   template<typename T>
0128   struct is_terminal: /* using makes VS2015 choke, hence we derive */
0129     mp11::mp_contains<acceptable_type_list,T>{};
0130   template<typename T>
0131   struct is_implementation:std::integral_constant< /* idem */
0132     bool,
0133     is_terminal<T>::value||
0134     variant_model_is_subvariant<T,Ts...>::value
0135   >{};
0136 
0137 private:
0138   template<typename T>
0139   using enable_if_terminal=
0140     typename std::enable_if<is_terminal<T>::value>::type*;
0141   template<typename T>
0142   using enable_if_not_terminal=
0143     typename std::enable_if<!is_terminal<T>::value>::type*;
0144 
0145 public:
0146   template<typename T> static type_index index()
0147   {
0148     return mp11::mp_find<acceptable_type_list,T>::value;
0149   }
0150 
0151   template<typename T,enable_if_terminal<T> =nullptr>
0152   static type_index subindex(const T&){return index<T>();}
0153 
0154 private:
0155   template<typename... Qs>
0156   struct subindex_lambda
0157   {
0158     template<typename I>
0159     std::size_t operator()(I)const
0160     {
0161       return mp11::mp_find<
0162         acceptable_type_list,mp11::mp_at<mp11::mp_list<Qs...>,I>>::value;
0163     }
0164   };
0165 
0166 public:
0167   template<
0168     template<typename...> class V,typename... Qs,
0169     enable_if_not_terminal<V<Qs...>> =nullptr>
0170   static type_index subindex(const V<Qs...>& x)
0171   {
0172     static constexpr auto not_found=mp11::mp_size<acceptable_type_list>::value;
0173     auto i=x.index();
0174     if(i>=sizeof...(Qs))return not_found;
0175     else return mp11::mp_with_index<sizeof...(Qs)>(
0176       i,subindex_lambda<Qs...>{});
0177   }
0178 
0179   template<typename T,enable_if_terminal<T> =nullptr>
0180   static void* subaddress(T& x){return boost::addressof(x);}
0181 
0182   template<typename T,enable_if_terminal<T> =nullptr>
0183   static const void* subaddress(const T& x){return boost::addressof(x);}
0184 
0185   template<typename T,enable_if_not_terminal<T> =nullptr>
0186   static void* subaddress(T& x)
0187   {
0188     return const_cast<void*>(subaddress(const_cast<const T&>(x)));
0189   }
0190   
0191 private:
0192   struct subaddress_visitor
0193   {
0194     template<typename T>
0195     const void* operator()(const T& x)const
0196     {
0197       return static_cast<const void*>(boost::addressof(x));
0198     }
0199   };
0200 
0201 public:
0202   template<typename T,enable_if_not_terminal<T> =nullptr>
0203   static const void* subaddress(const T& x)
0204   {
0205     return invoke_visit(subaddress_visitor{},x);
0206   }
0207 
0208   template<typename T,enable_if_terminal<T> =nullptr>
0209   static const std::type_info& subtype_info(const T& x)
0210   {
0211     return typeid(x);
0212   }
0213 
0214 private:
0215   struct subtype_info_visitor
0216   {
0217     template<typename T>
0218     const std::type_info& operator()(const T&)const{return typeid(T);}
0219   };
0220 
0221 public:
0222   template<typename T,enable_if_not_terminal<T> =nullptr>
0223   static const std::type_info& subtype_info(const T& x)
0224   {
0225     return invoke_visit(subtype_info_visitor{},x);
0226   }
0227 
0228   using base_iterator=fixed_variant_iterator<value_type>;
0229   using const_base_iterator=fixed_variant_iterator<const value_type>;
0230   using base_sentinel=value_type*;
0231   using const_base_sentinel=const value_type*;
0232   template<typename T>
0233   using iterator=fixed_variant_alternative_iterator<value_type,T>;
0234   template<typename T>
0235   using const_iterator=fixed_variant_alternative_iterator<value_type,const T>;
0236   template<typename Allocator>
0237   using segment_backend=detail::segment_backend<variant_model,Allocator>;
0238   template<typename T,typename Allocator>
0239   using segment_backend_implementation=
0240     packed_segment<variant_model,T,Allocator>;
0241 
0242   static base_iterator nonconst_iterator(const_base_iterator it)
0243   {
0244     return base_iterator{
0245       const_cast<value_type*>(static_cast<const value_type*>(it)),it.stride()};
0246   }
0247 
0248   template<typename T>
0249   static iterator<T> nonconst_iterator(const_iterator<T> it)
0250   {
0251     return {const_cast<T*>(static_cast<const T*>(it))};
0252   }
0253 
0254 private:
0255   template<typename,typename,typename>
0256   friend class packed_segment;
0257 
0258   template<typename T>
0259   using final_type=fixed_variant_impl::fixed_variant_closure<
0260      T,fixed_variant_impl::fixed_variant<Ts...>>;
0261 
0262   template<typename T>
0263   static const value_type* value_ptr(const T* p)noexcept
0264   {
0265     return reinterpret_cast<const final_type<T>*>(p);
0266   }
0267 };
0268 
0269 } /* namespace poly_collection::detail */
0270 
0271 } /* namespace poly_collection */
0272 
0273 } /* namespace boost */
0274 
0275 #endif