1 #ifndef SILICIUM_VARIANT_HPP
2 #define SILICIUM_VARIANT_HPP
5 #include <silicium/detail/argument_of.hpp>
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>
20 template <
class Visitor,
class Variant>
21 auto apply_visitor(Visitor &&visitor, Variant &&
variant) ->
typename std::decay<Visitor>::type::result_type
34 template <
class First,
class ...T>
40 #if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 408
44 std::array<
char,
sizeof(First)>
head;
55 template <
class Which, std::
size_t Size>
65 which_type
which() const BOOST_NOEXCEPT
67 return *
reinterpret_cast<which_type
const *
>(bytes.data() + which_offset);
70 void which(which_type value) BOOST_NOEXCEPT
72 *
reinterpret_cast<which_type *
>(bytes.data() + which_offset) = value;
80 char const &
storage() const BOOST_NOEXCEPT
87 typedef unsigned alignment_unit;
92 padding =
sizeof(alignment_unit),
93 padded_size = (used_size + padding - 1) / padding * padding
95 std::array<char, padded_size> bytes;
105 static_cast<T *
>(
storage)->~T();
111 auto &dest = *
static_cast<T *
>(destination);
112 auto &src = *
static_cast<T *
>(source);
119 auto &dest = *
static_cast<T *
>(destination);
120 auto &src = *
static_cast<T
const *
>(source);
127 auto &dest = *
static_cast<T *
>(destination);
128 auto &src = *
static_cast<T *
>(source);
135 auto &dest = *
static_cast<T *
>(destination);
136 auto &src = *
static_cast<T
const *
>(source);
141 bool equals(
void const *left,
void const *right)
143 auto &left_ = *
static_cast<T
const *
>(left);
144 auto &right_ = *
static_cast<T
const *
>(right);
145 return left_ == right_;
149 bool less(
void const *left,
void const *right)
151 auto &left_ = *
static_cast<T
const *
>(left);
152 auto &right_ = *
static_cast<T
const *
>(right);
153 return left_ < right_;
156 template <
class Visitor,
class T,
class Result>
159 return std::forward<Visitor>(visitor)(*static_cast<T *>(element));
162 template <
class Visitor,
class T,
class Result>
165 return std::forward<Visitor>(visitor)(*static_cast<T const *>(element));
168 #if SILICIUM_COMPILER_HAS_VARIADIC_PACK_EXPANSION
169 template <
class First,
class ...Rest>
175 template <
class ...Sequence>
178 template <
class First,
class ...Rest>
185 #if SILICIUM_COMPILER_HAS_VARIADIC_PACK_EXPANSION
186 template <
class ...All>
189 typedef boost::mpl::vector<All...> type;
194 template <
class ...All>
197 template <
class Head,
class ...Tail>
200 typedef typename boost::mpl::push_front<
209 typedef boost::mpl::vector<>
type;
213 template <
class Element,
class ...All>
214 struct index_of : boost::mpl::find<typename make_mpl_vector<All...>::type, Element>::type::pos
218 template <
class ...T>
221 template <
class First,
class ...T>
225 #if BOOST_VERSION >= 105400
226 boost::is_nothrow_move_constructible<First>,
227 boost::is_nothrow_move_assignable<First>
229 std::is_nothrow_move_constructible<First>,
230 std::is_nothrow_move_assignable<First>
243 template <
class Constructed>
249 return Constructed(std::forward<T>(argument));
253 template <
bool IsCopyable,
class ...T>
256 template <
class ...T>
261 is_noexcept_movable =
262 #if SILICIUM_COMPILER_HAS_WORKING_NOEXCEPT
274 typedef typename first<T...>::type constructed;
275 new (
reinterpret_cast<constructed *
>(&
storage.storage())) constructed();
283 template <class U = void, class V = typename boost::enable_if_c<is_noexcept_movable, U>::type>
286 storage.which(other.storage.which());
290 template <class U = void, class V = typename boost::enable_if_c<is_noexcept_movable, U>::type>
293 if (
storage.which() == other.which())
301 storage.which(other.storage.which());
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<
318 boost::mpl::bool_<(
index_of<CleanU, T...>::value <
sizeof...(T))>
325 new (&
storage.storage()) CleanU(std::forward<U>(value));
331 std::size_t Index =
index_of<Requested, T...>::value
336 new (&
storage.storage()) Requested(std::forward<Args>(args)...);
339 which_type
which() const BOOST_NOEXCEPT
344 template <
class Visitor>
345 auto apply_visitor(Visitor &&visitor) ->
typename std::decay<Visitor>::type::result_type
347 typedef typename std::decay<Visitor>::type::result_type result;
348 static std::array<result (*)(Visitor &&,
void *),
sizeof...(T)>
const f
350 &apply_visitor_impl<Visitor, T, result>...
352 return f[
storage.which()](std::forward<Visitor>(visitor), &
storage.storage());
355 template <
class Visitor>
356 auto apply_visitor(Visitor &&visitor) const -> typename
std::decay<Visitor>::type::result_type
358 typedef typename std::decay<Visitor>::type::result_type result;
359 static std::array<result(*)(Visitor &&,
void const *),
sizeof...(T)>
const f
361 &apply_visitor_const_impl<Visitor, T, result>...
363 return f[
storage.which()](std::forward<Visitor>(visitor), &
storage.storage());
368 if (
storage.which() != other.storage.which())
372 static std::array<bool(*)(
void const *,
void const *),
sizeof...(T)>
const f =
376 return f[
storage.which()](&
storage.storage(), &other.storage.storage());
381 if (
storage.which() > other.storage.which())
385 if (
storage.which() < other.storage.which())
389 static std::array<bool(*)(
void const *,
void const *),
sizeof...(T)>
const f =
393 return f[
storage.which()](&
storage.storage(), &other.storage.storage());
396 template <
bool IsOtherCopyable,
class ...U>
411 static std::array<void(*)(
void *,
void *),
sizeof...(T)>
const f =
413 &detail::move_construct_storage<T>...
415 f[
which](&destination, &source);
420 static std::array<void(*)(
void *),
sizeof...(T)>
const f =
422 &detail::destroy_storage<T>...
424 f[
which](&destroyed);
429 static std::array<void(*)(
void *,
void *),
sizeof...(T)>
const f =
431 &detail::move_storage<T>...
433 f[
which](&destination, &source);
440 template <class ...T>
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<
462 boost::mpl::bool_<(
index_of<CleanU, T...>::value <
sizeof...(T))>
471 template <
class Requested,
class ...Args>
473 :
base(i,
std::forward<Args>(args)...)
485 this->storage.
which(other.storage.which());
497 if (this->storage.
which() == other.storage.which())
507 this->storage.
which(other.storage.which());
514 template <
bool IsOtherCopyable,
class ...U>
524 static std::array<void(*)(
void *,
void const *),
sizeof...(T)>
const f =
526 &detail::copy_construct_storage<T>...
528 f[
which](&destination, &source);
531 static void copy_storage(which_type which,
char &destination,
char const &source)
533 static std::array<void(*)(
void *,
void const *),
sizeof...(T)>
const f =
535 &detail::copy_storage<T>...
537 f[
which](&destination, &source);
541 template <
class ...T>
544 template <
class First,
class ...T>
548 Si::is_copy_constructible<First>,
549 Si::is_copy_assignable<First>
567 #if SILICIUM_HAS_PROPER_COPY_TRAITS
572 #if SILICIUM_COMPILER_HAS_USING
573 template <
class ...T>
576 template <
class ...T>
599 template <
bool IsCopyable,
class ...T>
607 #if SILICIUM_COMPILER_HAS_USING
608 template <
class ...T>
609 using variant = detail::select_variant_base<T...>;
611 template <
class ...T>
620 template <
class First,
class ...Initializer,
class =
typename boost::disable_if<boost::is_same<boost::decay<First>::type,
variant>,
void>::type>
622 : base(
std::forward<First>(first),
std::forward<Initializer>(init)...)
627 : base(
std::
move(static_cast<base &>(other)))
632 : base(static_cast<base const &>(other))
636 template <class Content, class = typename boost::disable_if<boost::is_same<boost::decay<Content>::type, variant>,
void>::type>
637 variant &operator = (Content &&other)
639 static_cast<base &
>(*this) = std::forward<Content>(other);
643 variant &operator = (variant &&other) BOOST_NOEXCEPT
645 static_cast<base &
>(*this) =
std::move(static_cast<base &>(other));
649 variant &operator = (variant
const &other)
651 static_cast<base &
>(*this) =
static_cast<base
const &
>(other);
655 template <
class Other>
658 base::assign(
static_cast<typename std::decay<Other>::type::base
const &
>(other));
666 template <
class ...T>
669 return !(left == right);
672 template <
class ...T>
675 return (right < left);
678 template <
class ...T>
681 return !(left > right);
684 template <
class ...T>
687 return !(left < right);
695 return std::hash<T>()(element);
699 template <
class Element>
707 template <
class Other>
714 template <
class Element,
class ...T>
720 template <
class Element>
728 template <
class Other>
735 template <
class Element,
class ...T>
742 template <
class Element,
class ...T>
751 template <
class Result,
class ...Functions>
754 template <
class Result,
class Head>
765 Result
operator()(
typename argument_of<Head>::type argument)
const
767 return (*m_head)(std::forward<typename argument_of<Head>::type>(argument));
775 template <
class Result,
class Head,
class ...Tail>
789 Result
operator()(
typename argument_of<Head>::type argument)
const
791 return (*m_head)(std::forward<typename argument_of<Head>::type>(argument));
800 template <
class Result,
class ...T,
class ...Visitors>
807 template <
class Result,
class ...T,
class ...Visitors>
817 template <
class ...T>
818 struct hash<
Si::variant<T...>>
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