base_model.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. #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. template<typename Allocator>
  68. using segment_backend=detail::segment_backend<base_model,Allocator>;
  69. template<typename Derived,typename Allocator>
  70. using segment_backend_implementation=
  71. packed_segment<base_model,Derived,Allocator>;
  72. static base_iterator nonconst_iterator(const_base_iterator it)
  73. {
  74. return {
  75. const_cast<value_type*>(static_cast<const value_type*>(it)),
  76. it.stride()
  77. };
  78. }
  79. template<typename T>
  80. static iterator<T> nonconst_iterator(const_iterator<T> it)
  81. {
  82. return const_cast<iterator<T>>(it);
  83. }
  84. private:
  85. template<typename,typename,typename>
  86. friend class packed_segment;
  87. template<typename Derived>
  88. static const Base* value_ptr(const Derived* p)noexcept
  89. {
  90. return p;
  91. }
  92. };
  93. } /* namespace poly_collection::detail */
  94. } /* namespace poly_collection */
  95. } /* namespace boost */
  96. #endif