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