compact_storage.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * https://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * Copyright (c) 2022 Andrey Semashev
  7. */
  8. /*!
  9. * \file scope/detail/compact_storage.hpp
  10. *
  11. * This header contains utility helpers for implementing compact storage
  12. * for class members. In particular, it allows to leverage empty base optimization (EBO).
  13. */
  14. #ifndef BOOST_SCOPE_DETAIL_COMPACT_STORAGE_HPP_INCLUDED_
  15. #define BOOST_SCOPE_DETAIL_COMPACT_STORAGE_HPP_INCLUDED_
  16. #include <type_traits>
  17. #include <boost/scope/detail/config.hpp>
  18. #include <boost/scope/detail/type_traits/is_final.hpp>
  19. #include <boost/scope/detail/type_traits/negation.hpp>
  20. #include <boost/scope/detail/type_traits/conjunction.hpp>
  21. #include <boost/scope/detail/header.hpp>
  22. #ifdef BOOST_HAS_PRAGMA_ONCE
  23. #pragma once
  24. #endif
  25. namespace boost {
  26. namespace scope {
  27. namespace detail {
  28. //! The class allows to place data members in the tail padding of type \a T if the user's class derives from it
  29. template<
  30. typename T,
  31. typename Tag = void,
  32. bool = detail::conjunction< std::is_class< T >, detail::negation< detail::is_final< T > > >::value
  33. >
  34. class compact_storage :
  35. private T
  36. {
  37. public:
  38. template< typename... Args >
  39. constexpr compact_storage(Args&&... args) noexcept(std::is_nothrow_constructible< T, Args... >::value) :
  40. T(static_cast< Args&& >(args)...)
  41. {
  42. }
  43. compact_storage(compact_storage&&) = default;
  44. compact_storage& operator= (compact_storage&&) = default;
  45. compact_storage(compact_storage const&) = default;
  46. compact_storage& operator= (compact_storage const&) = default;
  47. T& get() noexcept
  48. {
  49. return *static_cast< T* >(this);
  50. }
  51. T const& get() const noexcept
  52. {
  53. return *static_cast< const T* >(this);
  54. }
  55. };
  56. template< typename T, typename Tag >
  57. class compact_storage< T, Tag, false >
  58. {
  59. private:
  60. T m_data;
  61. public:
  62. template< typename... Args >
  63. constexpr compact_storage(Args&&... args) noexcept(std::is_nothrow_constructible< T, Args... >::value) :
  64. m_data(static_cast< Args&& >(args)...)
  65. {
  66. }
  67. compact_storage(compact_storage&&) = default;
  68. compact_storage& operator= (compact_storage&&) = default;
  69. compact_storage(compact_storage const&) = default;
  70. compact_storage& operator= (compact_storage const&) = default;
  71. T& get() noexcept
  72. {
  73. return m_data;
  74. }
  75. T const& get() const noexcept
  76. {
  77. return m_data;
  78. }
  79. };
  80. } // namespace detail
  81. } // namespace scope
  82. } // namespace boost
  83. #include <boost/scope/detail/footer.hpp>
  84. #endif // BOOST_SCOPE_DETAIL_COMPACT_STORAGE_HPP_INCLUDED_