Silicium
variant.hpp
Go to the documentation of this file.
1 #ifndef SILICIUM_VARIANT_HPP
2 #define SILICIUM_VARIANT_HPP
3 
4 #include <silicium/is_handle.hpp>
5 #include <silicium/detail/argument_of.hpp>
6 #include <new>
7 #include <array>
8 #include <memory>
9 #include <boost/variant/static_visitor.hpp>
10 #include <boost/mpl/find.hpp>
11 #include <boost/mpl/push_front.hpp>
12 #include <boost/mpl/vector.hpp>
13 #include <boost/mpl/contains.hpp>
14 #include <boost/integer.hpp>
15 #include <boost/optional.hpp>
16 #include <boost/type_traits.hpp>
17 
18 namespace Si
19 {
20  template <class Visitor, class Variant>
21  auto apply_visitor(Visitor &&visitor, Variant &&variant) -> typename std::decay<Visitor>::type::result_type
22  {
23  return std::forward<Variant>(variant).apply_visitor(std::forward<Visitor>(visitor));
24  }
25 
26  template <class T>
27  struct inplace {};
28 
29  namespace detail
30  {
31  template <class ...T>
32  struct union_;
33 
34  template <class First, class ...T>
35  struct union_<First, T...>
36  {
37  union
38  {
39 #ifndef _MSC_VER
40 #if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 408
41  alignas(First)
42 #endif
43 #endif
44  std::array<char, sizeof(First)> head;
45  union_<T...> tail;
46  }
47  content;
48  };
49 
50  template <>
51  struct union_<>
52  {
53  };
54 
55  template <class Which, std::size_t Size>
57  {
58  typedef Which which_type;
59 
60  combined_storage() BOOST_NOEXCEPT
61  {
62  which(0);
63  }
64 
65  which_type which() const BOOST_NOEXCEPT
66  {
67  return *reinterpret_cast<which_type const *>(bytes.data() + which_offset);
68  }
69 
70  void which(which_type value) BOOST_NOEXCEPT
71  {
72  *reinterpret_cast<which_type *>(bytes.data() + which_offset) = value;
73  }
74 
75  char &storage() BOOST_NOEXCEPT
76  {
77  return *bytes.data();
78  }
79 
80  char const &storage() const BOOST_NOEXCEPT
81  {
82  return *bytes.data();
83  }
84 
85  private:
86 
87  typedef unsigned alignment_unit;
88  enum
89  {
90  which_offset = (Size + sizeof(which_type) - 1) / sizeof(which_type) * sizeof(which_type),
91  used_size = which_offset + sizeof(which_type),
92  padding = sizeof(alignment_unit),
93  padded_size = (used_size + padding - 1) / padding * padding
94  };
95  std::array<char, padded_size> bytes;
96  };
97 
98  template <class T>
99  void destroy_storage(void *storage) BOOST_NOEXCEPT
100  {
101 #ifdef _MSC_VER
102  //VC++ 2013: Silence (wrong) warning about unreferenced parameter
103  (void)storage;
104 #endif
105  static_cast<T *>(storage)->~T();
106  }
107 
108  template <class T>
109  void move_construct_storage(void *destination, void *source) BOOST_NOEXCEPT
110  {
111  auto &dest = *static_cast<T *>(destination);
112  auto &src = *static_cast<T *>(source);
113  new (&dest) T(std::move(src));
114  }
115 
116  template <class T>
117  void copy_construct_storage(void *destination, void const *source)
118  {
119  auto &dest = *static_cast<T *>(destination);
120  auto &src = *static_cast<T const *>(source);
121  new (&dest) T(src);
122  }
123 
124  template <class T>
125  void move_storage(void *destination, void *source) BOOST_NOEXCEPT
126  {
127  auto &dest = *static_cast<T *>(destination);
128  auto &src = *static_cast<T *>(source);
129  dest = std::move(src);
130  }
131 
132  template <class T>
133  void copy_storage(void *destination, void const *source)
134  {
135  auto &dest = *static_cast<T *>(destination);
136  auto &src = *static_cast<T const *>(source);
137  dest = src;
138  }
139 
140  template <class T>
141  bool equals(void const *left, void const *right)
142  {
143  auto &left_ = *static_cast<T const *>(left);
144  auto &right_ = *static_cast<T const *>(right);
145  return left_ == right_;
146  }
147 
148  template <class T>
149  bool less(void const *left, void const *right)
150  {
151  auto &left_ = *static_cast<T const *>(left);
152  auto &right_ = *static_cast<T const *>(right);
153  return left_ < right_;
154  }
155 
156  template <class Visitor, class T, class Result>
157  Result apply_visitor_impl(Visitor &&visitor, void *element)
158  {
159  return std::forward<Visitor>(visitor)(*static_cast<T *>(element));
160  }
161 
162  template <class Visitor, class T, class Result>
163  Result apply_visitor_const_impl(Visitor &&visitor, void const *element)
164  {
165  return std::forward<Visitor>(visitor)(*static_cast<T const *>(element));
166  }
167 
168 #if SILICIUM_COMPILER_HAS_VARIADIC_PACK_EXPANSION
169  template <class First, class ...Rest>
170  struct first
171  {
172  typedef First type;
173  };
174 #else
175  template <class ...Sequence>
176  struct first;
177 
178  template <class First, class ...Rest>
179  struct first<First, Rest...>
180  {
181  typedef First type;
182  };
183 #endif
184 
185 #if SILICIUM_COMPILER_HAS_VARIADIC_PACK_EXPANSION
186  template <class ...All>
187  struct make_mpl_vector
188  {
189  typedef boost::mpl::vector<All...> type;
190  };
191 #else
192  //workaround for GCC 4.6
193 
194  template <class ...All>
196 
197  template <class Head, class ...Tail>
198  struct make_mpl_vector<Head, Tail...>
199  {
200  typedef typename boost::mpl::push_front<
201  typename make_mpl_vector<Tail...>::type,
202  Head
204  };
205 
206  template <>
208  {
209  typedef boost::mpl::vector<> type;
210  };
211 #endif
212 
213  template <class Element, class ...All>
214  struct index_of : boost::mpl::find<typename make_mpl_vector<All...>::type, Element>::type::pos
215  {
216  };
217 
218  template <class ...T>
220 
221  template <class First, class ...T>
222  struct are_noexcept_movable<First, T...>
223  : boost::mpl::and_<
224  boost::mpl::and_<
225 #if BOOST_VERSION >= 105400
226  boost::is_nothrow_move_constructible<First>,
227  boost::is_nothrow_move_assignable<First>
228 #else
229  std::is_nothrow_move_constructible<First>,
230  std::is_nothrow_move_assignable<First>
231 #endif
232  >,
234  >::type
235  {
236  };
237 
238  template <>
239  struct are_noexcept_movable<> : std::true_type
240  {
241  };
242 
243  template <class Constructed>
244  struct construction_visitor : boost::static_visitor<Constructed>
245  {
246  template <class T>
247  Constructed operator()(T &&argument) const
248  {
249  return Constructed(std::forward<T>(argument));
250  }
251  };
252 
253  template <bool IsCopyable, class ...T>
254  struct variant_base;
255 
256  template <class ...T>
257  struct variant_base<false, T...>
258  {
259  enum
260  {
261  is_noexcept_movable =
262 #if SILICIUM_COMPILER_HAS_WORKING_NOEXCEPT
263  detail::are_noexcept_movable<T...>::value
264 #else
265  1
266 #endif
267  };
268 
269  typedef unsigned which_type;
270  typedef boost::mpl::vector<T...> element_types;
271 
272  variant_base() BOOST_NOEXCEPT
273  {
274  typedef typename first<T...>::type constructed;
275  new (reinterpret_cast<constructed *>(&storage.storage())) constructed();
276  }
277 
278  ~variant_base() BOOST_NOEXCEPT
279  {
280  destroy_storage(storage.which(), storage.storage());
281  }
282 
283  template <class U = void, class V = typename boost::enable_if_c<is_noexcept_movable, U>::type>
284  variant_base(variant_base &&other) BOOST_NOEXCEPT
285  {
286  storage.which(other.storage.which());
287  move_construct_storage(storage.which(), storage.storage(), other.storage.storage());
288  }
289 
290  template <class U = void, class V = typename boost::enable_if_c<is_noexcept_movable, U>::type>
291  variant_base &operator = (variant_base &&other) BOOST_NOEXCEPT
292  {
293  if (storage.which() == other.which())
294  {
295  move_storage(storage.which(), storage.storage(), other.storage.storage());
296  }
297  else
298  {
299  destroy_storage(storage.which(), storage.storage());
300  move_construct_storage(other.storage.which(), storage.storage(), other.storage.storage());
301  storage.which(other.storage.which());
302  }
303  return *this;
304  }
305 
306  template <
307  class U,
308  class CleanU = typename std::decay<U>::type,
309  std::size_t Index = index_of<CleanU, T...>::value,
310  class NoFastVariant = typename std::enable_if<
311  boost::mpl::and_<
312  boost::mpl::not_<
313  std::is_base_of<
314  variant_base,
315  CleanU
316  >
317  >,
318  boost::mpl::bool_<(index_of<CleanU, T...>::value < sizeof...(T))>
319  >::value,
320  void
321  >::type>
322  variant_base(U &&value)
323  {
324  storage.which(Index);
325  new (&storage.storage()) CleanU(std::forward<U>(value));
326  }
327 
328  template <
329  class Requested,
330  class ...Args,
331  std::size_t Index = index_of<Requested, T...>::value
332  >
333  explicit variant_base(inplace<Requested>, Args &&...args)
334  {
335  storage.which(Index);
336  new (&storage.storage()) Requested(std::forward<Args>(args)...);
337  }
338 
339  which_type which() const BOOST_NOEXCEPT
340  {
341  return storage.which();
342  }
343 
344  template <class Visitor>
345  auto apply_visitor(Visitor &&visitor) -> typename std::decay<Visitor>::type::result_type
346  {
347  typedef typename std::decay<Visitor>::type::result_type result;
348  static std::array<result (*)(Visitor &&, void *), sizeof...(T)> const f
349  {{
350  &apply_visitor_impl<Visitor, T, result>...
351  }};
352  return f[storage.which()](std::forward<Visitor>(visitor), &storage.storage());
353  }
354 
355  template <class Visitor>
356  auto apply_visitor(Visitor &&visitor) const -> typename std::decay<Visitor>::type::result_type
357  {
358  typedef typename std::decay<Visitor>::type::result_type result;
359  static std::array<result(*)(Visitor &&, void const *), sizeof...(T)> const f
360  {{
361  &apply_visitor_const_impl<Visitor, T, result>...
362  }};
363  return f[storage.which()](std::forward<Visitor>(visitor), &storage.storage());
364  }
365 
366  bool operator == (variant_base const &other) const
367  {
368  if (storage.which() != other.storage.which())
369  {
370  return false;
371  }
372  static std::array<bool(*)(void const *, void const *), sizeof...(T)> const f =
373  {{
374  &equals<T>...
375  }};
376  return f[storage.which()](&storage.storage(), &other.storage.storage());
377  }
378 
379  bool operator < (variant_base const &other) const
380  {
381  if (storage.which() > other.storage.which())
382  {
383  return false;
384  }
385  if (storage.which() < other.storage.which())
386  {
387  return true;
388  }
389  static std::array<bool(*)(void const *, void const *), sizeof...(T)> const f =
390  {{
391  &less<T>...
392  }};
393  return f[storage.which()](&storage.storage(), &other.storage.storage());
394  }
395 
396  template <bool IsOtherCopyable, class ...U>
398  {
400  }
401 
402  protected: //TODO: make private somehow
403 
404  typedef typename boost::uint_value_t<sizeof...(T)>::least internal_which_type;
405  typedef combined_storage<internal_which_type, sizeof(union_<T...>)> storage_type; //TODO: ensure proper alignment
406 
408 
409  static void move_construct_storage(which_type which, char &destination, char &source) BOOST_NOEXCEPT
410  {
411  static std::array<void(*)(void *, void *), sizeof...(T)> const f =
412  {{
413  &detail::move_construct_storage<T>...
414  }};
415  f[which](&destination, &source);
416  }
417 
418  static void destroy_storage(which_type which, char &destroyed) BOOST_NOEXCEPT
419  {
420  static std::array<void(*)(void *), sizeof...(T)> const f =
421  {{
422  &detail::destroy_storage<T>...
423  }};
424  f[which](&destroyed);
425  }
426 
427  static void move_storage(which_type which, char &destination, char &source) BOOST_NOEXCEPT
428  {
429  static std::array<void(*)(void *, void *), sizeof...(T)> const f =
430  {{
431  &detail::move_storage<T>...
432  }};
433  f[which](&destination, &source);
434  }
435 
438  };
439 
440  template <class ...T>
441  struct variant_base<true, T...> : variant_base<false, T...>
442  {
443  typedef variant_base<false, T...> base;
444  typedef typename base::which_type which_type;
445 
446  variant_base() BOOST_NOEXCEPT
447  {
448  }
449 
450  template <
451  class U,
452  class CleanU = typename std::decay<U>::type,
453  std::size_t Index = index_of<CleanU, T...>::value,
454  class NoFastVariant = typename std::enable_if<
455  boost::mpl::and_<
456  boost::mpl::not_<
457  std::is_base_of<
458  variant_base,
459  CleanU
460  >
461  >,
462  boost::mpl::bool_<(index_of<CleanU, T...>::value < sizeof...(T))>
463  >::value,
464  void
465  >::type>
466  variant_base(U &&value)
467  : base(std::forward<U>(value))
468  {
469  }
470 
471  template <class Requested, class ...Args>
472  explicit variant_base(inplace<Requested> i, Args &&...args)
473  : base(i, std::forward<Args>(args)...)
474  {
475  }
476 
477  variant_base(variant_base &&other) BOOST_NOEXCEPT
478  : base(std::move(other))
479  {
480  }
481 
483  : base()
484  {
485  this->storage.which(other.storage.which());
486  copy_construct_storage(this->storage.which(), this->storage.storage(), other.storage.storage());
487  }
488 
489  variant_base &operator = (variant_base &&other) BOOST_NOEXCEPT
490  {
491  base::operator = (std::move(other));
492  return *this;
493  }
494 
495  variant_base &operator = (variant_base const &other)
496  {
497  if (this->storage.which() == other.storage.which())
498  {
499  copy_storage(this->storage.which(), this->storage.storage(), other.storage.storage());
500  }
501  else
502  {
503  typename base::storage_type temporary;
504  copy_construct_storage(other.storage.which(), temporary.storage(), other.storage.storage());
505  base::destroy_storage(this->storage.which(), this->storage.storage());
506  base::move_construct_storage(other.storage.which(), this->storage.storage(), temporary.storage());
507  this->storage.which(other.storage.which());
508  }
509  return *this;
510  }
511 
512  using base::assign;
513 
514  template <bool IsOtherCopyable, class ...U>
516  {
518  }
519 
520  private:
521 
522  static void copy_construct_storage(which_type which, char &destination, char const &source)
523  {
524  static std::array<void(*)(void *, void const *), sizeof...(T)> const f =
525  {{
526  &detail::copy_construct_storage<T>...
527  }};
528  f[which](&destination, &source);
529  }
530 
531  static void copy_storage(which_type which, char &destination, char const &source)
532  {
533  static std::array<void(*)(void *, void const *), sizeof...(T)> const f =
534  {{
535  &detail::copy_storage<T>...
536  }};
537  f[which](&destination, &source);
538  }
539  };
540 
541  template <class ...T>
542  struct are_copyable;
543 
544  template <class First, class ...T>
545  struct are_copyable<First, T...>
546  : boost::mpl::and_<
547  boost::mpl::and_<
548  Si::is_copy_constructible<First>,
549  Si::is_copy_assignable<First>
550  >,
551  are_copyable<T...>
552  >::type
553  {
554  };
555 
556  template <>
557  struct are_copyable<> : std::true_type
558  {
559  };
560 
564 
565  //In VC++ 2013 Update 3 the type traits is_copy_constructible and is_copy_assignable still return true for unique_ptr,
566  //so this assert would fail.
567 #if SILICIUM_HAS_PROPER_COPY_TRAITS
568  //GCC 4.6 with Boost < 1.55 is also a problem
569  BOOST_STATIC_ASSERT((!are_copyable<int, std::unique_ptr<int>>::value));
570 #endif
571 
572 #if SILICIUM_COMPILER_HAS_USING
573  template <class ...T>
574  using select_variant_base = variant_base<are_copyable<T...>::value, T...>;
575 #else
576  template <class ...T>
578  {
579  typedef variant_base<are_copyable<T...>::value, T...> type;
580  };
581 #endif
582 
583  struct ostream_visitor : boost::static_visitor<>
584  {
585  std::ostream *out;
586 
587  explicit ostream_visitor(std::ostream &out)
588  : out(&out)
589  {
590  }
591 
592  template <class T>
593  void operator()(T const &value) const
594  {
595  *out << value;
596  }
597  };
598 
599  template <bool IsCopyable, class ...T>
600  std::ostream &operator << (std::ostream &out, variant_base<IsCopyable, T...> const &v)
601  {
603  return out;
604  }
605  }
606 
607 #if SILICIUM_COMPILER_HAS_USING
608  template <class ...T>
609  using variant = detail::select_variant_base<T...>;
610 #else
611  template <class ...T>
613  {
614  typedef typename detail::select_variant_base<T...>::type base;
615 
616  variant() BOOST_NOEXCEPT
617  {
618  }
619 
620  template <class First, class ...Initializer, class = typename boost::disable_if<boost::is_same<boost::decay<First>::type, variant>, void>::type>
621  variant(First &&first, Initializer &&...init)
622  : base(std::forward<First>(first), std::forward<Initializer>(init)...)
623  {
624  }
625 
626  variant(variant &&other) BOOST_NOEXCEPT
627  : base(std::move(static_cast<base &>(other)))
628  {
629  }
630 
631  variant(variant const &other)
632  : base(static_cast<base const &>(other))
633  {
634  }
635 
636  template <class Content, class = typename boost::disable_if<boost::is_same<boost::decay<Content>::type, variant>, void>::type>
637  variant &operator = (Content &&other)
638  {
639  static_cast<base &>(*this) = std::forward<Content>(other);
640  return *this;
641  }
642 
643  variant &operator = (variant &&other) BOOST_NOEXCEPT
644  {
645  static_cast<base &>(*this) = std::move(static_cast<base &>(other));
646  return *this;
647  }
648 
649  variant &operator = (variant const &other)
650  {
651  static_cast<base &>(*this) = static_cast<base const &>(other);
652  return *this;
653  }
654 
655  template <class Other>
656  void assign(Other &&other)
657  {
658  base::assign(static_cast<typename std::decay<Other>::type::base const &>(other));
659  }
660  };
661 #endif
662 
663  BOOST_STATIC_ASSERT(is_handle<variant<int>>::value);
664  BOOST_STATIC_ASSERT((is_handle<variant<int, nothing>>::value));
665 
666  template <class ...T>
667  bool operator != (variant<T...> const &left, variant<T...> const &right)
668  {
669  return !(left == right);
670  }
671 
672  template <class ...T>
673  bool operator > (variant<T...> const &left, variant<T...> const &right)
674  {
675  return (right < left);
676  }
677 
678  template <class ...T>
679  bool operator <= (variant<T...> const &left, variant<T...> const &right)
680  {
681  return !(left > right);
682  }
683 
684  template <class ...T>
685  bool operator >= (variant<T...> const &left, variant<T...> const &right)
686  {
687  return !(left < right);
688  }
689 
690  struct hash_visitor : boost::static_visitor<std::size_t>
691  {
692  template <class T>
693  std::size_t operator()(T const &element) const
694  {
695  return std::hash<T>()(element);
696  }
697  };
698 
699  template <class Element>
700  struct try_get_visitor : boost::static_visitor<boost::optional<Element>>
701  {
702  boost::optional<Element> operator()(Element value) const
703  {
704  return std::move(value);
705  }
706 
707  template <class Other>
708  boost::optional<Element> operator()(Other const &) const
709  {
710  return boost::none;
711  }
712  };
713 
714  template <class Element, class ...T>
715  boost::optional<Element> try_get(variant<T...> &from)
716  {
717  return apply_visitor(try_get_visitor<Element>{}, from);
718  }
719 
720  template <class Element>
721  struct try_get_ptr_visitor : boost::static_visitor<Element *>
722  {
723  Element * operator()(Element &value) const BOOST_NOEXCEPT
724  {
725  return &value;
726  }
727 
728  template <class Other>
729  Element * operator()(Other const &) const BOOST_NOEXCEPT
730  {
731  return nullptr;
732  }
733  };
734 
735  template <class Element, class ...T>
736  Element *try_get_ptr(variant<T...> &from) BOOST_NOEXCEPT
737  {
738  BOOST_STATIC_ASSERT((boost::mpl::contains<boost::mpl::vector<T...>, Element>::value));
740  }
741 
742  template <class Element, class ...T>
743  typename std::add_const<Element>::type *try_get_ptr(variant<T...> const &from) BOOST_NOEXCEPT
744  {
745  BOOST_STATIC_ASSERT((boost::mpl::contains<boost::mpl::vector<T...>, Element>::value));
746  return apply_visitor(try_get_ptr_visitor<typename std::add_const<Element>::type>{}, from);
747  }
748 
749  namespace detail
750  {
751  template <class Result, class ...Functions>
752  struct overloader;
753 
754  template <class Result, class Head>
755  struct overloader<Result, Head>
756  {
757  //for apply_visitor
758  typedef Result result_type;
759 
760  explicit overloader(Head &head)
761  : m_head(&head)
762  {
763  }
764 
765  Result operator()(typename argument_of<Head>::type argument) const
766  {
767  return (*m_head)(std::forward<typename argument_of<Head>::type>(argument));
768  }
769 
770  private:
771 
772  Head *m_head;
773  };
774 
775  template <class Result, class Head, class ...Tail>
776  struct overloader<Result, Head, Tail...> : overloader<Result, Tail...>
777  {
779 
780  //for apply_visitor
781  typedef Result result_type;
782 
783  explicit overloader(Head &head, Tail &...tail)
784  : overloader<Result, Tail...>(tail...)
785  , m_head(&head)
786  {
787  }
788 
789  Result operator()(typename argument_of<Head>::type argument) const
790  {
791  return (*m_head)(std::forward<typename argument_of<Head>::type>(argument));
792  }
793 
794  private:
795 
796  Head *m_head;
797  };
798  }
799 
800  template <class Result, class ...T, class ...Visitors>
801  Result visit(variant<T...> &variant, Visitors &&...visitors)
802  {
803  detail::overloader<Result, Visitors...> ov(visitors...);
804  return Si::apply_visitor(ov, variant);
805  }
806 
807  template <class Result, class ...T, class ...Visitors>
808  Result visit(variant<T...> const &variant, Visitors &&...visitors)
809  {
810  detail::overloader<Result, Visitors...> ov(visitors...);
811  return Si::apply_visitor(ov, variant);
812  }
813 }
814 
815 namespace std
816 {
817  template <class ...T>
818  struct hash<Si::variant<T...>>
819  {
820  std::size_t operator()(Si::variant<T...> const &v) const
821  {
822  return Si::apply_visitor(Si::hash_visitor(), v);
823  }
824  };
825 }
826 
827 //TODO: which is always 0, so this can be made as small as sizeof(int)
828 BOOST_STATIC_ASSERT(sizeof(Si::variant<boost::uint32_t>) == (2 * sizeof(boost::uint32_t)));
829 
830 //TODO: which is always 0, so this can be made as small as sizeof(int *)
831 BOOST_STATIC_ASSERT(sizeof(Si::variant<int *>) == (sizeof(boost::uint32_t) + sizeof(int *)));
832 
833 BOOST_STATIC_ASSERT(sizeof(Si::variant<std::hash<Si::variant<int>>>) == sizeof(boost::uint32_t));
834 
835 #endif
auto apply_visitor(Visitor &&visitor) const -> typename std::decay< Visitor >::type::result_type
Definition: variant.hpp:356
Definition: variant.hpp:244
std::remove_reference< T >::type && move(T &&ref)
Definition: move.hpp:10
Result apply_visitor_const_impl(Visitor &&visitor, void const *element)
Definition: variant.hpp:163
boost::optional< Element > operator()(Element value) const
Definition: variant.hpp:702
boost::mpl::vector type
Definition: variant.hpp:209
variant_base(inplace< Requested >, Args &&...args)
Definition: variant.hpp:333
base::which_type which_type
Definition: variant.hpp:444
Element * try_get_ptr(variant< T... > &from) BOOST_NOEXCEPT
Definition: variant.hpp:736
variant_base< false, T... > base
Definition: variant.hpp:443
Definition: variant.hpp:219
ostream_visitor(std::ostream &out)
Definition: variant.hpp:587
void assign(variant_base< IsOtherCopyable, U... > &&other)
Definition: variant.hpp:397
Definition: variant.hpp:257
Definition: variant.hpp:176
variant_base(variant_base const &other)
Definition: variant.hpp:482
variant_base(variant_base &&other) BOOST_NOEXCEPT
Definition: variant.hpp:284
detail::select_variant_base< T... >::type base
Definition: variant.hpp:614
Definition: variant.hpp:214
Definition: absolute_path.hpp:352
Definition: variant.hpp:542
union_< T... > tail
Definition: variant.hpp:45
boost::mpl::vector< T... > element_types
Definition: variant.hpp:270
Definition: absolute_path.hpp:19
static void move_construct_storage(which_type which, char &destination, char &source) BOOST_NOEXCEPT
Definition: variant.hpp:409
variant_base(inplace< Requested > i, Args &&...args)
Definition: variant.hpp:472
Definition: variant.hpp:195
First type
Definition: variant.hpp:181
static void move_storage(which_type which, char &destination, char &source) BOOST_NOEXCEPT
Definition: variant.hpp:427
Definition: variant.hpp:752
std::size_t operator()(Si::variant< T... > const &v) const
Definition: variant.hpp:820
Definition: variant.hpp:32
Definition: variant.hpp:700
Definition: variant.hpp:27
void assign(variant_base< IsOtherCopyable, U... > const &other)
Definition: variant.hpp:515
bool less(void const *left, void const *right)
Definition: variant.hpp:149
variant(First &&first, Initializer &&...init)
Definition: variant.hpp:621
variant_base< are_copyable< T... >::value, T... > type
Definition: variant.hpp:579
variant() BOOST_NOEXCEPT
Definition: variant.hpp:616
overloader(Head &head)
Definition: variant.hpp:760
std::array< char, sizeof(First)> head
Definition: variant.hpp:44
void assign(Other &&other)
Definition: variant.hpp:656
Result operator()(typename argument_of< Head >::type argument) const
Definition: variant.hpp:765
Which which_type
Definition: variant.hpp:58
Definition: variant.hpp:254
void move_construct_storage(void *destination, void *source) BOOST_NOEXCEPT
Definition: variant.hpp:109
auto apply_visitor(Visitor &&visitor) -> typename std::decay< Visitor >::type::result_type
Definition: variant.hpp:345
void move_storage(void *destination, void *source) BOOST_NOEXCEPT
Definition: variant.hpp:125
SILICIUM_USE_RESULT bool operator==(absolute_path const &left, ComparableToPath const &right)
Definition: absolute_path.hpp:169
variant_base() BOOST_NOEXCEPT
Definition: variant.hpp:446
Definition: variant.hpp:612
Element * operator()(Element &value) const BOOST_NOEXCEPT
Definition: variant.hpp:723
combined_storage() BOOST_NOEXCEPT
Definition: variant.hpp:60
which_type which() const BOOST_NOEXCEPT
Definition: variant.hpp:65
Result result_type
Definition: variant.hpp:758
SILICIUM_USE_RESULT bool operator<(absolute_path const &left, absolute_path const &right)
Definition: absolute_path.hpp:214
variant(variant &&other) BOOST_NOEXCEPT
Definition: variant.hpp:626
overloader(Head &head, Tail &...tail)
Definition: variant.hpp:783
Definition: variant.hpp:721
Result visit(variant< T... > &variant, Visitors &&...visitors)
Definition: variant.hpp:801
Definition: variant.hpp:690
boost::optional< Element > try_get(variant< T... > &from)
Definition: variant.hpp:715
bool operator>=(variant< T... > const &left, variant< T... > const &right)
Definition: variant.hpp:685
variant(variant const &other)
Definition: variant.hpp:631
Definition: variant.hpp:577
bool operator<=(variant< T... > const &left, variant< T... > const &right)
Definition: variant.hpp:679
auto apply_visitor(Visitor &&visitor, Variant &&variant) -> typename std::decay< Visitor >::type::result_type
Definition: variant.hpp:21
which_type which() const BOOST_NOEXCEPT
Definition: variant.hpp:339
variant_base(U &&value)
Definition: variant.hpp:322
storage_type storage
Definition: variant.hpp:407
void copy_construct_storage(void *destination, void const *source)
Definition: variant.hpp:117
#define SILICIUM_DELETED_FUNCTION(f)
Definition: config.hpp:111
boost::optional< Element > operator()(Other const &) const
Definition: variant.hpp:708
std::size_t operator()(T const &element) const
Definition: variant.hpp:693
Element * operator()(Other const &) const BOOST_NOEXCEPT
Definition: variant.hpp:729
bool equals(void const *left, void const *right)
Definition: variant.hpp:141
char & storage() BOOST_NOEXCEPT
Definition: variant.hpp:75
Constructed operator()(T &&argument) const
Definition: variant.hpp:247
Result result_type
Definition: variant.hpp:781
std::ostream & operator<<(std::ostream &out, variant_base< IsCopyable, T... > const &v)
Definition: variant.hpp:600
void operator()(T const &value) const
Definition: variant.hpp:593
SILICIUM_USE_RESULT bool operator!=(absolute_path const &left, ComparableToPath const &right)
Definition: absolute_path.hpp:201
void copy_storage(void *destination, void const *source)
Definition: variant.hpp:133
unsigned which_type
Definition: variant.hpp:269
~variant_base() BOOST_NOEXCEPT
Definition: variant.hpp:278
variant_base() BOOST_NOEXCEPT
Definition: variant.hpp:272
Result apply_visitor_impl(Visitor &&visitor, void *element)
Definition: variant.hpp:157
Definition: variant.hpp:583
void which(which_type value) BOOST_NOEXCEPT
Definition: variant.hpp:70
Definition: variant.hpp:56
Result operator()(typename argument_of< Head >::type argument) const
Definition: variant.hpp:789
bool operator>(variant< T... > const &left, variant< T... > const &right)
Definition: variant.hpp:673
static void destroy_storage(which_type which, char &destroyed) BOOST_NOEXCEPT
Definition: variant.hpp:418
boost::uint_value_t< sizeof...(T)>::least internal_which_type
Definition: variant.hpp:404
variant_base(U &&value)
Definition: variant.hpp:466
BOOST_STATIC_ASSERT(!is_handle< non_copyable >::value)
char const & storage() const BOOST_NOEXCEPT
Definition: variant.hpp:80
std::ostream * out
Definition: variant.hpp:585
variant_base(variant_base &&other) BOOST_NOEXCEPT
Definition: variant.hpp:477
boost::mpl::push_front< typename make_mpl_vector< Tail... >::type, Head >::type type
Definition: variant.hpp:203
void destroy_storage(void *storage) BOOST_NOEXCEPT
Definition: variant.hpp:99