• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
7 #ifndef BOOST_HISTOGRAM_AXIS_METADATA_BASE_HPP
8 #define BOOST_HISTOGRAM_AXIS_METADATA_BASE_HPP
9 
10 #include <boost/histogram/axis/traits.hpp>
11 #include <boost/histogram/detail/replace_type.hpp>
12 #include <string>
13 #include <type_traits>
14 
15 namespace boost {
16 namespace histogram {
17 namespace axis {
18 
19 /** Meta data holder with space optimization for empty meta data types.
20 
21   Allows write-access to metadata even if const.
22 
23   @tparam Metadata Wrapped meta data type.
24  */
25 template <class Metadata, bool Detail>
26 class metadata_base {
27 protected:
28   using metadata_type = Metadata;
29 
30   // std::string explicitly guarantees nothrow only in C++17
31   static_assert(std::is_same<metadata_type, std::string>::value ||
32                     std::is_nothrow_move_constructible<metadata_type>::value,
33                 "metadata must be nothrow move constructible");
34 
35   metadata_base() = default;
36   metadata_base(const metadata_base&) = default;
37   metadata_base& operator=(const metadata_base&) = default;
38 
39   // make noexcept because std::string is nothrow move constructible only in C++17
metadata_base(metadata_base && o)40   metadata_base(metadata_base&& o) noexcept : data_(std::move(o.data_)) {}
metadata_base(metadata_type && o)41   metadata_base(metadata_type&& o) noexcept : data_(std::move(o)) {}
42   // make noexcept because std::string is nothrow move constructible only in C++17
operator =(metadata_base && o)43   metadata_base& operator=(metadata_base&& o) noexcept {
44     data_ = std::move(o.data_);
45     return *this;
46   }
47 
48 private:
49   mutable metadata_type data_;
50 
51 public:
52   /// Returns reference to metadata.
metadata()53   metadata_type& metadata() noexcept { return data_; }
54 
55   /// Returns reference to mutable metadata from const axis.
metadata() const56   metadata_type& metadata() const noexcept { return data_; }
57 };
58 
59 #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
60 
61 // specialization for empty metadata
62 template <class Metadata>
63 class metadata_base<Metadata, true> {
64 protected:
65   using metadata_type = Metadata;
66 
67   metadata_base() = default;
68 
metadata_base(metadata_type &&)69   metadata_base(metadata_type&&) {}
operator =(metadata_type &&)70   metadata_base& operator=(metadata_type&&) { return *this; }
71 
72 public:
metadata()73   metadata_type& metadata() noexcept {
74     return static_cast<const metadata_base&>(*this).metadata();
75   }
76 
metadata() const77   metadata_type& metadata() const noexcept {
78     static metadata_type data;
79     return data;
80   }
81 };
82 
83 template <class Metadata, class Detail = detail::replace_default<Metadata, std::string>>
84 using metadata_base_t =
85     metadata_base<Detail, (std::is_empty<Detail>::value && std::is_final<Detail>::value)>;
86 
87 #endif
88 
89 } // namespace axis
90 } // namespace histogram
91 } // namespace boost
92 
93 #endif
94