ゴミ箱
variant.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_DETAIL_VARIANT_HPP
11 #define BOOST_BEAST_DETAIL_VARIANT_HPP
12 
14 #include <boost/assert.hpp>
15 #include <cstddef>
16 #include <tuple>
17 #include <type_traits>
18 
19 namespace boost {
20 namespace beast {
21 namespace detail {
22 
23 // This simple variant gets the job done without
24 // causing too much trouble with template depth:
25 //
26 // * Always allows an empty state I==0
27 // * emplace() and get() support 1-based indexes only
28 // * Basic exception guarantee
29 // * Max 255 types
30 //
31 template<class... TN>
32 class variant
33 {
34  typename std::aligned_storage<
35  max_sizeof<TN...>(),
36  max_alignof<TN...>()
37  >::type buf_;
38  unsigned char i_ = 0;
39 
40  template<std::size_t I>
41  using type = typename std::tuple_element<
42  I , std::tuple<TN...>>::type;
43 
44  template<std::size_t I>
45  using C = std::integral_constant<std::size_t, I>;
46 
47 public:
48  variant() = default;
49 
51  {
52  if(i_)
53  destroy(C<0>{});
54  }
55 
56  // 0 = empty
57  unsigned char
58  index() const
59  {
60  return i_;
61  }
62 
63  // moved-from object becomes empty
64  variant(variant&& other)
65  {
66  i_ = other.move(&buf_, C<0>{});
67  }
68 
69  variant(variant const& other)
70  {
71  i_ = other.copy(&buf_, C<0>{});
72  }
73 
74  // moved-from object becomes empty
76  {
77  if(i_ != 0)
78  destroy(C<0>{});
79  i_ = other.move(&buf_, C<0>{});
80  return *this;
81  }
82 
83  variant& operator=(variant const& other)
84  {
85  if(i_ != 0)
86  destroy(C<0>{});
87  i_ = other.copy(&buf_, C<0>{});
88  return *this;
89  }
90 
91  template<std::size_t I, class... Args>
92  void
93  emplace(Args&&... args)
94  {
95  if(i_ != 0)
96  destroy(C<0>{});
97  new(&buf_) type<I-1>(
98  std::forward<Args>(args)...);
99  i_ = I;
100  }
101 
102  template<std::size_t I>
103  type<I-1>&
104  get()
105  {
106  BOOST_ASSERT(i_ == I);
107  return *reinterpret_cast<
108  type<I-1>*>(&buf_);
109  }
110 
111  template<std::size_t I>
112  type<I-1> const&
113  get() const
114  {
115  BOOST_ASSERT(i_ == I);
116  return *reinterpret_cast<
117  type<I-1> const*>(&buf_);
118  }
119 
120  void
122  {
123  if(i_ == 0)
124  return;
125  destroy(C<0>{});
126  }
127 
128 private:
129  void
130  destroy(C<sizeof...(TN)>)
131  {
132  return;
133  }
134 
135  template<std::size_t I>
136  void
137  destroy(C<I>)
138  {
139  if(i_ == I+1)
140  {
141  using T = type<I>;
142  get<I+1>().~T();
143  i_ = 0;
144  return;
145  }
146  destroy(C<I+1>{});
147  }
148 
149  unsigned char
150  move(void*, C<sizeof...(TN)>)
151  {
152  return 0;
153  }
154 
155  template<std::size_t I>
156  unsigned char
157  move(void* dest, C<I>)
158  {
159  if(i_ == I+1)
160  {
161  using T = type<I>;
162  new(dest) T{std::move(get<I+1>())};
163  get<I+1>().~T();
164  i_ = 0;
165  return I+1;
166  }
167  return move(dest, C<I+1>{});
168  }
169 
170  unsigned char
171  copy(void*, C<sizeof...(TN)>) const
172  {
173  return 0;
174  }
175 
176  template<std::size_t I>
177  unsigned char
178  copy(void* dest, C<I>) const
179  {
180  if(i_ == I+1)
181  {
182  using T = type<I>;
183  auto const& t = get<I+1>();
184  new(dest) T{t};
185  return I+1;
186  }
187  return copy(dest, C<I+1>{});
188  }
189 };
190 
191 } // detail
192 } // beast
193 } // boost
194 
195 #endif
~variant()
Definition: variant.hpp:50
Definition: async_result.hpp:20
variant(variant &&other)
Definition: variant.hpp:64
variant(variant const &other)
Definition: variant.hpp:69
void emplace(Args &&...args)
Definition: variant.hpp:93
variant & operator=(variant &&other)
Definition: variant.hpp:75
std::size_t constexpr max_sizeof()
Definition: type_traits.hpp:71
Definition: variant.hpp:32
void reset()
Definition: variant.hpp:121
unsigned char index() const
Definition: variant.hpp:58
variant & operator=(variant const &other)
Definition: variant.hpp:83