1 /* Copyright 2016-2018 Joaquin M Lopez Munoz. 2 * Distributed under the Boost Software License, Version 1.0. 3 * (See accompanying file LICENSE_1_0.txt or copy at 4 * http://www.boost.org/LICENSE_1_0.txt) 5 * 6 * See http://www.boost.org/libs/poly_collection for library home page. 7 */ 8 9 #ifndef BOOST_POLY_COLLECTION_DETAIL_BASE_MODEL_HPP 10 #define BOOST_POLY_COLLECTION_DETAIL_BASE_MODEL_HPP 11 12 #if defined(_MSC_VER) 13 #pragma once 14 #endif 15 16 #include <boost/core/addressof.hpp> 17 #include <boost/poly_collection/detail/is_final.hpp> 18 #include <boost/poly_collection/detail/packed_segment.hpp> 19 #include <boost/poly_collection/detail/stride_iterator.hpp> 20 #include <memory> 21 #include <type_traits> 22 #include <typeinfo> 23 #include <utility> 24 25 namespace boost{ 26 27 namespace poly_collection{ 28 29 namespace detail{ 30 31 /* model for base_collection */ 32 33 template<typename Base> 34 struct base_model 35 { 36 using value_type=Base; 37 template<typename Derived> 38 using is_implementation=std::is_base_of<Base,Derived>; 39 template<typename T> 40 using is_terminal=is_final<T>; //TODO: should we say !is_polymorhpic||is_final? 41 42 private: 43 template<typename T> 44 using enable_if_not_terminal= 45 typename std::enable_if<!is_terminal<T>::value>::type*; 46 template<typename T> 47 using enable_if_terminal= 48 typename std::enable_if<is_terminal<T>::value>::type*; 49 50 public: 51 template<typename T,enable_if_not_terminal<T> =nullptr> subtypeidboost::poly_collection::detail::base_model52 static const std::type_info& subtypeid(const T& x){return typeid(x);} 53 54 template<typename T,enable_if_terminal<T> =nullptr> subtypeidboost::poly_collection::detail::base_model55 static const std::type_info& subtypeid(const T&){return typeid(T);} 56 57 template<typename T,enable_if_not_terminal<T> =nullptr> subaddressboost::poly_collection::detail::base_model58 static void* subaddress(T& x) 59 { 60 return dynamic_cast<void*>(boost::addressof(x)); 61 } 62 63 template<typename T,enable_if_not_terminal<T> =nullptr> subaddressboost::poly_collection::detail::base_model64 static const void* subaddress(const T& x) 65 { 66 return dynamic_cast<const void*>(boost::addressof(x)); 67 } 68 69 template<typename T,enable_if_terminal<T> =nullptr> subaddressboost::poly_collection::detail::base_model70 static void* subaddress(T& x){return boost::addressof(x);} 71 72 template<typename T,enable_if_terminal<T> =nullptr> subaddressboost::poly_collection::detail::base_model73 static const void* subaddress(const T& x){return boost::addressof(x);} 74 75 using base_iterator=stride_iterator<Base>; 76 using const_base_iterator=stride_iterator<const Base>; 77 using base_sentinel=Base*; 78 using const_base_sentinel=const Base*; 79 template<typename Derived> 80 using iterator=Derived*; 81 template<typename Derived> 82 using const_iterator=const Derived*; 83 template<typename Allocator> 84 using segment_backend=detail::segment_backend<base_model,Allocator>; 85 template<typename Derived,typename Allocator> 86 using segment_backend_implementation= 87 packed_segment<base_model,Derived,Allocator>; 88 nonconst_iteratorboost::poly_collection::detail::base_model89 static base_iterator nonconst_iterator(const_base_iterator it) 90 { 91 return { 92 const_cast<value_type*>(static_cast<const value_type*>(it)), 93 it.stride() 94 }; 95 } 96 97 template<typename T> nonconst_iteratorboost::poly_collection::detail::base_model98 static iterator<T> nonconst_iterator(const_iterator<T> it) 99 { 100 return const_cast<iterator<T>>(it); 101 } 102 103 private: 104 template<typename,typename,typename> 105 friend class packed_segment; 106 107 template<typename Derived> value_ptrboost::poly_collection::detail::base_model108 static const Base* value_ptr(const Derived* p)noexcept 109 { 110 return p; 111 } 112 }; 113 114 } /* namespace poly_collection::detail */ 115 116 } /* namespace poly_collection */ 117 118 } /* namespace boost */ 119 120 #endif 121