base_model.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /* Copyright 2016-2024 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. #ifndef BOOST_POLY_COLLECTION_DETAIL_BASE_MODEL_HPP
  9. #define BOOST_POLY_COLLECTION_DETAIL_BASE_MODEL_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/core/addressof.hpp>
  14. #include <boost/poly_collection/detail/is_final.hpp>
  15. #include <boost/poly_collection/detail/packed_segment.hpp>
  16. #include <boost/poly_collection/detail/stride_iterator.hpp>
  17. #include <memory>
  18. #include <type_traits>
  19. #include <typeinfo>
  20. #include <utility>
  21. namespace boost{
  22. namespace poly_collection{
  23. namespace detail{
  24. /* model for base_collection */
  25. template<typename Base>
  26. struct base_model
  27. {
  28. using value_type=Base;
  29. using type_index=std::type_info;
  30. template<typename Derived>
  31. using is_implementation=std::is_base_of<Base,Derived>;
  32. template<typename T>
  33. using is_terminal=is_final<T>; //TODO: should we say !is_polymorhpic||is_final?
  34. private:
  35. template<typename T>
  36. using enable_if_not_terminal=
  37. typename std::enable_if<!is_terminal<T>::value>::type*;
  38. template<typename T>
  39. using enable_if_terminal=
  40. typename std::enable_if<is_terminal<T>::value>::type*;
  41. public:
  42. template<typename T>
  43. static const std::type_info& index(){return typeid(T);}
  44. template<typename T,enable_if_not_terminal<T> =nullptr>
  45. static const std::type_info& subindex(const T& x){return typeid(x);}
  46. template<typename T,enable_if_terminal<T> =nullptr>
  47. static const std::type_info& subindex(const T&){return typeid(T);}
  48. template<typename T,enable_if_not_terminal<T> =nullptr>
  49. static void* subaddress(T& x)
  50. {
  51. return dynamic_cast<void*>(boost::addressof(x));
  52. }
  53. template<typename T,enable_if_not_terminal<T> =nullptr>
  54. static const void* subaddress(const T& x)
  55. {
  56. return dynamic_cast<const void*>(boost::addressof(x));
  57. }
  58. template<typename T,enable_if_terminal<T> =nullptr>
  59. static void* subaddress(T& x){return boost::addressof(x);}
  60. template<typename T,enable_if_terminal<T> =nullptr>
  61. static const void* subaddress(const T& x){return boost::addressof(x);}
  62. using base_iterator=stride_iterator<Base>;
  63. using const_base_iterator=stride_iterator<const Base>;
  64. using base_sentinel=Base*;
  65. using const_base_sentinel=const Base*;
  66. template<typename Derived>
  67. using iterator=Derived*;
  68. template<typename Derived>
  69. using const_iterator=const Derived*;
  70. template<typename Allocator>
  71. using segment_backend=detail::segment_backend<base_model,Allocator>;
  72. template<typename Derived,typename Allocator>
  73. using segment_backend_implementation=
  74. packed_segment<base_model,Derived,Allocator>;
  75. static base_iterator nonconst_iterator(const_base_iterator it)
  76. {
  77. return {
  78. const_cast<value_type*>(static_cast<const value_type*>(it)),
  79. it.stride()
  80. };
  81. }
  82. template<typename T>
  83. static iterator<T> nonconst_iterator(const_iterator<T> it)
  84. {
  85. return const_cast<iterator<T>>(it);
  86. }
  87. private:
  88. template<typename,typename,typename>
  89. friend class packed_segment;
  90. template<typename Derived>
  91. static const Base* value_ptr(const Derived* p)noexcept
  92. {
  93. return p;
  94. }
  95. };
  96. } /* namespace poly_collection::detail */
  97. } /* namespace poly_collection */
  98. } /* namespace boost */
  99. #endif