Imported Upstream version 1.71.0
[platform/upstream/boost.git] / boost / histogram / detail / compressed_pair.hpp
1 // Copyright 2018 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_DETAIL_COMPRESSED_PAIR_HPP
8 #define BOOST_HISTOGRAM_DETAIL_COMPRESSED_PAIR_HPP
9
10 #include <type_traits>
11 #include <utility>
12
13 namespace boost {
14 namespace histogram {
15 namespace detail {
16
17 template <class T1, class T2, bool B>
18 class compressed_pair_impl;
19
20 // normal implementation
21 template <class T1, class T2>
22 class compressed_pair_impl<T1, T2, false> {
23 public:
24   using first_type = T1;
25   using second_type = T2;
26
27   compressed_pair_impl() = default;
28
29   compressed_pair_impl(first_type&& x, second_type&& y)
30       : first_(std::move(x)), second_(std::move(y)) {}
31
32   compressed_pair_impl(const first_type& x, const second_type& y)
33       : first_(x), second_(y) {}
34
35   compressed_pair_impl(first_type&& x) : first_(std::move(x)) {}
36   compressed_pair_impl(const first_type& x) : first_(x) {}
37
38   first_type& first() noexcept { return first_; }
39   second_type& second() noexcept { return second_; }
40   const first_type& first() const noexcept { return first_; }
41   const second_type& second() const noexcept { return second_; }
42
43 private:
44   first_type first_;
45   second_type second_;
46 };
47
48 // compressed implementation, T2 consumes no space
49 template <class T1, class T2>
50 class compressed_pair_impl<T1, T2, true> : protected T2 {
51 public:
52   using first_type = T1;
53   using second_type = T2;
54
55   compressed_pair_impl() = default;
56
57   compressed_pair_impl(first_type&& x, second_type&& y)
58       : T2(std::move(y)), first_(std::move(x)) {}
59
60   compressed_pair_impl(const first_type& x, const second_type& y) : T2(y), first_(x) {}
61
62   compressed_pair_impl(first_type&& x) : first_(std::move(x)) {}
63   compressed_pair_impl(const first_type& x) : first_(x) {}
64
65   first_type& first() noexcept { return first_; }
66   second_type& second() noexcept { return static_cast<second_type&>(*this); }
67   const first_type& first() const noexcept { return first_; }
68   const second_type& second() const noexcept {
69     return static_cast<const second_type&>(*this);
70   }
71
72 private:
73   first_type first_;
74 };
75
76 template <typename T1, typename T2>
77 using compressed_pair =
78     compressed_pair_impl<T1, T2, (!std::is_final<T2>::value && std::is_empty<T2>::value)>;
79
80 template <class T, class U>
81 void swap(compressed_pair<T, U>& a, compressed_pair<T, U>& b) noexcept(
82     std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_assignable<
83         T>::value&& std::is_nothrow_move_constructible<U>::value&&
84         std::is_nothrow_move_assignable<U>::value) {
85   using std::swap;
86   swap(a.first(), b.first());
87   swap(a.second(), b.second());
88 }
89
90 } // namespace detail
91 } // namespace histogram
92 } // namespace boost
93
94 #endif