File indexing completed on 2025-01-30 09:55:09
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 template<typename Concrete>
0104 using is_implementation=std::true_type;
0105
0106 template<typename T>
0107 using is_terminal=any_model_is_terminal<T>;
0108
0109 template<typename T>
0110 static const std::type_info& subtypeid(const T&){return typeid(T);}
0111
0112 template<
0113 typename Concept2,typename T,
0114 any_model_enable_if_has_typeid_<Concept2,T> =nullptr
0115 >
0116 static const std::type_info& subtypeid(
0117 const type_erasure::any<Concept2,T>& a)
0118 {
0119 return type_erasure::typeid_of(a);
0120 }
0121
0122 template<typename T>
0123 static void* subaddress(T& x){return boost::addressof(x);}
0124
0125 template<typename T>
0126 static const void* subaddress(const T& x){return boost::addressof(x);}
0127
0128 template<
0129 typename Concept2,typename T,
0130 any_model_enable_if_has_typeid_<Concept2,T> =nullptr
0131 >
0132 static void* subaddress(type_erasure::any<Concept2,T>& a)
0133 {
0134 return type_erasure::any_cast<void*>(&a);
0135 }
0136
0137 template<
0138 typename Concept2,typename T,
0139 any_model_enable_if_has_typeid_<Concept2,T> =nullptr
0140 >
0141 static const void* subaddress(const type_erasure::any<Concept2,T>& a)
0142 {
0143 return type_erasure::any_cast<const void*>(&a);
0144 }
0145
0146 using base_iterator=any_iterator<value_type>;
0147 using const_base_iterator=any_iterator<const value_type>;
0148 using base_sentinel=value_type*;
0149 using const_base_sentinel=const value_type*;
0150 template<typename Concrete>
0151 using iterator=Concrete*;
0152 template<typename Concrete>
0153 using const_iterator=const Concrete*;
0154 template<typename Allocator>
0155 using segment_backend=detail::segment_backend<any_model,Allocator>;
0156 template<typename Concrete,typename Allocator>
0157 using segment_backend_implementation=
0158 split_segment<any_model,Concrete,Allocator>;
0159
0160 static base_iterator nonconst_iterator(const_base_iterator it)
0161 {
0162 return base_iterator{
0163 const_cast<value_type*>(static_cast<const value_type*>(it))};
0164 }
0165
0166 template<typename T>
0167 static iterator<T> nonconst_iterator(const_iterator<T> it)
0168 {
0169 return const_cast<iterator<T>>(it);
0170 }
0171
0172 private:
0173 template<typename,typename,typename>
0174 friend class split_segment;
0175
0176 template<typename Concrete>
0177 static value_type make_value_type(Concrete& x){return value_type{x};}
0178
0179 template<typename Concept2,typename T>
0180 static value_type make_value_type(type_erasure::any<Concept2,T>& x)
0181 {
0182
0183
0184
0185
0186 using ref_type=type_erasure::any<Concept2,T>;
0187 using make_ref=any_model_make_reference<type_erasure::_self,ref_type>;
0188 using concept_=typename type_erasure::concept_of<value_type>::type;
0189
0190 auto b=type_erasure::make_binding<
0191 mpl::map1<mpl::pair<type_erasure::_self,ref_type>>>();
0192
0193 return {
0194 type_erasure::call(type_erasure::binding<make_ref>{b},make_ref{},x),
0195 type_erasure::binding<concept_>{b}
0196 };
0197 }
0198 };
0199
0200 }
0201
0202 }
0203
0204 }
0205
0206 #endif