base_model.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* Copyright 2016-2017 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. template<typename Derived>
  30. using is_implementation=std::is_base_of<Base,Derived>;
  31. template<typename T>
  32. using is_terminal=is_final<T>; //TODO: should we say !is_polymorhpic||is_final?
  33. private:
  34. template<typename T>
  35. using enable_if_not_terminal=
  36. typename std::enable_if<!is_terminal<T>::value>::type*;
  37. template<typename T>
  38. using enable_if_terminal=
  39. typename std::enable_if<is_terminal<T>::value>::type*;
  40. public:
  41. template<typename T,enable_if_not_terminal<T> =nullptr>
  42. static const std::type_info& subtypeid(const T& x){return typeid(x);}
  43. template<typename T,enable_if_terminal<T> =nullptr>
  44. static const std::type_info& subtypeid(const T&){return typeid(T);}
  45. template<typename T,enable_if_not_terminal<T> =nullptr>
  46. static void* subaddress(T& x)
  47. {
  48. return dynamic_cast<void*>(boost::addressof(x));
  49. }
  50. template<typename T,enable_if_not_terminal<T> =nullptr>
  51. static const void* subaddress(const T& x)
  52. {
  53. return dynamic_cast<const void*>(boost::addressof(x));
  54. }
  55. template<typename T,enable_if_terminal<T> =nullptr>
  56. static void* subaddress(T& x){return boost::addressof(x);}
  57. template<typename T,enable_if_terminal<T> =nullptr>
  58. static const void* subaddress(const T& x){return boost::addressof(x);}
  59. using base_iterator=stride_iterator<Base>;
  60. using const_base_iterator=stride_iterator<const Base>;
  61. using base_sentinel=Base*;
  62. using const_base_sentinel=const Base*;
  63. template<typename Derived>
  64. using iterator=Derived*;
  65. template<typename Derived>
  66. using const_iterator=const Derived*;
  67. using segment_backend=detail::segment_backend<base_model>;
  68. template<typename Derived,typename Allocator>
  69. using segment_backend_implementation=packed_segment<
  70. base_model,
  71. Derived,
  72. typename std::allocator_traits<Allocator>::template rebind_alloc<Derived>
  73. >;
  74. using segment_backend_unique_ptr=
  75. typename segment_backend::segment_backend_unique_ptr;
  76. static base_iterator nonconst_iterator(const_base_iterator it)
  77. {
  78. return {
  79. const_cast<value_type*>(static_cast<const value_type*>(it)),
  80. it.stride()
  81. };
  82. }
  83. template<typename T>
  84. static iterator<T> nonconst_iterator(const_iterator<T> it)
  85. {
  86. return const_cast<iterator<T>>(it);
  87. }
  88. template<typename Derived,typename Allocator>
  89. static segment_backend_unique_ptr make(const Allocator& al)
  90. {
  91. return segment_backend_implementation<Derived,Allocator>::new_(al,al);
  92. }
  93. private:
  94. template<typename,typename,typename>
  95. friend class packed_segment;
  96. template<typename Derived>
  97. static const Base* value_ptr(const Derived* p)noexcept
  98. {
  99. return p;
  100. }
  101. };
  102. } /* namespace poly_collection::detail */
  103. } /* namespace poly_collection */
  104. } /* namespace boost */
  105. #endif