]>
Commit | Line | Data |
---|---|---|
92f5a8d4 | 1 | /* Copyright 2016-2018 Joaquin M Lopez Munoz. |
b32b8144 FG |
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> | |
52 | static const std::type_info& subtypeid(const T& x){return typeid(x);} | |
53 | ||
54 | template<typename T,enable_if_terminal<T> =nullptr> | |
55 | static const std::type_info& subtypeid(const T&){return typeid(T);} | |
56 | ||
57 | template<typename T,enable_if_not_terminal<T> =nullptr> | |
58 | 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> | |
64 | 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> | |
70 | static void* subaddress(T& x){return boost::addressof(x);} | |
71 | ||
72 | template<typename T,enable_if_terminal<T> =nullptr> | |
73 | 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*; | |
92f5a8d4 TL |
83 | template<typename Allocator> |
84 | using segment_backend=detail::segment_backend<base_model,Allocator>; | |
b32b8144 | 85 | template<typename Derived,typename Allocator> |
92f5a8d4 TL |
86 | using segment_backend_implementation= |
87 | packed_segment<base_model,Derived,Allocator>; | |
b32b8144 FG |
88 | |
89 | 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> | |
98 | static iterator<T> nonconst_iterator(const_iterator<T> it) | |
99 | { | |
100 | return const_cast<iterator<T>>(it); | |
101 | } | |
102 | ||
b32b8144 FG |
103 | private: |
104 | template<typename,typename,typename> | |
105 | friend class packed_segment; | |
106 | ||
107 | template<typename Derived> | |
108 | 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 |