File indexing completed on 2025-09-17 08:45:56
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_ANY_MODEL_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_ANY_MODEL_HPP
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/core/addressof.hpp>
0017 #include <boost/mpl/map/map10.hpp>
0018 #include <boost/mpl/pair.hpp>
0019 #include <boost/mpl/vector/vector10.hpp>
0020 #include <boost/poly_collection/detail/any_iterator.hpp>
0021 #include <boost/poly_collection/detail/is_acceptable.hpp>
0022 #include <boost/poly_collection/detail/segment_backend.hpp>
0023 #include <boost/poly_collection/detail/split_segment.hpp>
0024 #include <boost/type_erasure/any.hpp>
0025 #include <boost/type_erasure/any_cast.hpp>
0026 #include <boost/type_erasure/binding.hpp>
0027 #include <boost/type_erasure/builtin.hpp>
0028 #include <boost/type_erasure/concept_of.hpp>
0029 #include <boost/type_erasure/is_subconcept.hpp>
0030 #include <boost/type_erasure/relaxed.hpp>
0031 #include <boost/type_erasure/static_binding.hpp>
0032 #include <boost/type_erasure/typeid_of.hpp>
0033 #include <memory>
0034 #include <type_traits>
0035 #include <typeinfo>
0036 #include <utility>
0037
0038 namespace boost{
0039
0040 namespace poly_collection{
0041
0042 namespace detail{
0043
0044
0045
0046 template<typename Concept>
0047 struct any_model;
0048
0049
0050
0051
0052
0053 template<typename Concept,typename Concept2,typename T>
0054 struct is_acceptable<
0055 type_erasure::any<Concept2,T>,any_model<Concept>,
0056 typename std::enable_if<
0057 !type_erasure::is_relaxed<Concept2>::value&&
0058 !type_erasure::is_subconcept<type_erasure::assignable<>,Concept2>::value&&
0059 !type_erasure::is_subconcept<
0060 type_erasure::assignable<type_erasure::_self,type_erasure::_self&&>,
0061 Concept2>::value
0062 >::type
0063 >:std::false_type{};
0064
0065
0066
0067 template<typename Concept,typename T>
0068 using any_model_enable_if_has_typeid_=typename std::enable_if<
0069 type_erasure::is_subconcept<
0070 type_erasure::typeid_<typename std::decay<T>::type>,
0071 Concept
0072 >::value
0073 >::type*;
0074
0075 template<typename T,typename=void*>
0076 struct any_model_is_terminal:std::true_type{};
0077
0078 template<typename Concept,typename T>
0079 struct any_model_is_terminal<
0080 type_erasure::any<Concept,T>,any_model_enable_if_has_typeid_<Concept,T>
0081 >:std::false_type{};
0082
0083
0084
0085 template<typename T,typename Q>
0086 struct any_model_make_reference
0087 {
0088 static T& apply(Q& x){return x;}
0089 };
0090
0091 template<typename Concept>
0092 struct any_model
0093 {
0094 using value_type=type_erasure::any<
0095 typename std::conditional<
0096 type_erasure::is_subconcept<type_erasure::typeid_<>,Concept>::value,
0097 Concept,
0098 mpl::vector2<Concept,type_erasure::typeid_<>>
0099 >::type,
0100 type_erasure::_self&
0101 >;
0102
0103 using type_index=std::type_info;
0104
0105 template<typename Concrete>
0106 using is_implementation=std::true_type;
0107
0108 template<typename T>
0109 using is_terminal=any_model_is_terminal<T>;
0110
0111 template<typename T>
0112 static const std::type_info& index(){return typeid(T);}
0113
0114 template<typename T>
0115 static const std::type_info& subindex(const T&){return typeid(T);}
0116
0117 template<
0118 typename Concept2,typename T,
0119 any_model_enable_if_has_typeid_<Concept2,T> =nullptr
0120 >
0121 static const std::type_info& subindex(
0122 const type_erasure::any<Concept2,T>& a)
0123 {
0124 return type_erasure::typeid_of(a);
0125 }
0126
0127 template<typename T>
0128 static void* subaddress(T& x){return boost::addressof(x);}
0129
0130 template<typename T>
0131 static const void* subaddress(const T& x){return boost::addressof(x);}
0132
0133 template<
0134 typename Concept2,typename T,
0135 any_model_enable_if_has_typeid_<Concept2,T> =nullptr
0136 >
0137 static void* subaddress(type_erasure::any<Concept2,T>& a)
0138 {
0139 return type_erasure::any_cast<void*>(&a);
0140 }
0141
0142 template<
0143 typename Concept2,typename T,
0144 any_model_enable_if_has_typeid_<Concept2,T> =nullptr
0145 >
0146 static const void* subaddress(const type_erasure::any<Concept2,T>& a)
0147 {
0148 return type_erasure::any_cast<const void*>(&a);
0149 }
0150
0151 using base_iterator=any_iterator<value_type>;
0152 using const_base_iterator=any_iterator<const value_type>;
0153 using base_sentinel=value_type*;
0154 using const_base_sentinel=const value_type*;
0155 template<typename Concrete>
0156 using iterator=Concrete*;
0157 template<typename Concrete>
0158 using const_iterator=const Concrete*;
0159 template<typename Allocator>
0160 using segment_backend=detail::segment_backend<any_model,Allocator>;
0161 template<typename Concrete,typename Allocator>
0162 using segment_backend_implementation=
0163 split_segment<any_model,Concrete,Allocator>;
0164
0165 static base_iterator nonconst_iterator(const_base_iterator it)
0166 {
0167 return base_iterator{
0168 const_cast<value_type*>(static_cast<const value_type*>(it))};
0169 }
0170
0171 template<typename T>
0172 static iterator<T> nonconst_iterator(const_iterator<T> it)
0173 {
0174 return const_cast<iterator<T>>(it);
0175 }
0176
0177 private:
0178 template<typename,typename,typename>
0179 friend class split_segment;
0180
0181 template<typename Concrete>
0182 static value_type make_value_type(Concrete& x){return value_type{x};}
0183
0184 template<typename Concept2,typename T>
0185 static value_type make_value_type(type_erasure::any<Concept2,T>& x)
0186 {
0187
0188
0189
0190
0191 using ref_type=type_erasure::any<Concept2,T>;
0192 using make_ref=any_model_make_reference<type_erasure::_self,ref_type>;
0193 using concept_=typename type_erasure::concept_of<value_type>::type;
0194
0195 auto b=type_erasure::make_binding<
0196 mpl::map1<mpl::pair<type_erasure::_self,ref_type>>>();
0197
0198 return {
0199 type_erasure::call(type_erasure::binding<make_ref>{b},make_ref{},x),
0200 type_erasure::binding<concept_>{b}
0201 };
0202 }
0203 };
0204
0205 }
0206
0207 }
0208
0209 }
0210
0211 #endif