metadata_base.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright 2019 Hans Dembinski
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_HISTOGRAM_AXIS_METADATA_BASE_HPP
  7. #define BOOST_HISTOGRAM_AXIS_METADATA_BASE_HPP
  8. #include <boost/histogram/axis/traits.hpp>
  9. #include <boost/histogram/detail/replace_type.hpp>
  10. #include <string>
  11. #include <type_traits>
  12. namespace boost {
  13. namespace histogram {
  14. namespace axis {
  15. /** Meta data holder with space optimization for empty meta data types.
  16. Allows write-access to metadata even if const.
  17. @tparam Metadata Wrapped meta data type.
  18. */
  19. template <class Metadata, bool Detail>
  20. class metadata_base {
  21. protected:
  22. using metadata_type = Metadata;
  23. static_assert(std::is_default_constructible<metadata_type>::value,
  24. "metadata must be default constructible");
  25. static_assert(std::is_copy_constructible<metadata_type>::value,
  26. "metadata must be copy constructible");
  27. static_assert(std::is_copy_assignable<metadata_type>::value,
  28. "metadata must be copy assignable");
  29. // std::string explicitly guarantees nothrow only in C++17
  30. static_assert(std::is_same<metadata_type, std::string>::value ||
  31. std::is_nothrow_move_constructible<metadata_type>::value,
  32. "metadata must be nothrow move constructible");
  33. metadata_base() = default;
  34. metadata_base(const metadata_base&) = default;
  35. metadata_base& operator=(const metadata_base&) = default;
  36. // make noexcept because std::string is nothrow move constructible only in C++17
  37. metadata_base(metadata_base&& o) noexcept : data_(std::move(o.data_)) {}
  38. metadata_base(metadata_type&& o) noexcept : data_(std::move(o)) {}
  39. // make noexcept because std::string is nothrow move constructible only in C++17
  40. metadata_base& operator=(metadata_base&& o) noexcept {
  41. data_ = std::move(o.data_);
  42. return *this;
  43. }
  44. public:
  45. /// Returns reference to metadata.
  46. metadata_type& metadata() noexcept { return data_; }
  47. /// Returns reference to mutable metadata from const axis.
  48. metadata_type& metadata() const noexcept { return data_; }
  49. private:
  50. mutable metadata_type data_;
  51. };
  52. #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
  53. // specialization for empty metadata
  54. template <class Metadata>
  55. class metadata_base<Metadata, true> {
  56. protected:
  57. using metadata_type = Metadata;
  58. metadata_base() = default;
  59. metadata_base(metadata_type&&) {}
  60. metadata_base& operator=(metadata_type&&) { return *this; }
  61. public:
  62. metadata_type& metadata() noexcept {
  63. return static_cast<const metadata_base&>(*this).metadata();
  64. }
  65. metadata_type& metadata() const noexcept {
  66. static metadata_type data;
  67. return data;
  68. }
  69. };
  70. template <class Metadata, class Detail = detail::replace_default<Metadata, std::string>>
  71. using metadata_base_t =
  72. metadata_base<Detail, (std::is_empty<Detail>::value && std::is_final<Detail>::value)>;
  73. #endif
  74. } // namespace axis
  75. } // namespace histogram
  76. } // namespace boost
  77. #endif