File indexing completed on 2025-09-17 08:45:58
0001
0002
0003
0004
0005
0006
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 }}
0044
0045 namespace boost_poly_collection_invoke_visit_variant2{
0046
0047
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 }
0057
0058 namespace boost{
0059
0060 namespace poly_collection{
0061
0062 namespace detail{
0063
0064
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:
0129 mp11::mp_contains<acceptable_type_list,T>{};
0130 template<typename T>
0131 struct is_implementation:std::integral_constant<
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 }
0270
0271 }
0272
0273 }
0274
0275 #endif