variant.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2014-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_UTILITY_VARIANT_HPP
  14. #define RANGES_V3_UTILITY_VARIANT_HPP
  15. #include <range/v3/algorithm/copy.hpp>
  16. #include <range/v3/algorithm/move.hpp>
  17. #include <range/v3/detail/variant.hpp>
  18. #include <range/v3/iterator/move_iterators.hpp>
  19. #include <range/v3/iterator/operations.hpp>
  20. #include <range/v3/range/access.hpp>
  21. #include <range/v3/range/concepts.hpp>
  22. #include <range/v3/range/primitives.hpp>
  23. #include <range/v3/detail/prologue.hpp>
  24. namespace ranges
  25. {
  26. /// \cond
  27. namespace detail
  28. {
  29. template<typename T, std::size_t N, typename Index>
  30. struct indexed_datum<T[N], Index>
  31. {
  32. private:
  33. union
  34. {
  35. char c;
  36. T data_[N];
  37. };
  38. void fill_default_(T * p, std::true_type)
  39. {
  40. for(; p != ranges::end(data_); ++p)
  41. ::new((void *)p) T{};
  42. }
  43. void fill_default_(T * p, std::false_type)
  44. {
  45. RANGES_EXPECT(p == ranges::end(data_));
  46. }
  47. public:
  48. CPP_member
  49. constexpr CPP_ctor(indexed_datum)(meta::nil_ = {})(
  50. requires default_constructible<T>)
  51. : data_{}
  52. {}
  53. CPP_member
  54. CPP_ctor(indexed_datum)(indexed_datum && that)(
  55. requires move_constructible<T>)
  56. {
  57. std::uninitialized_copy_n(make_move_iterator(that.data_), N, data_);
  58. }
  59. CPP_member
  60. CPP_ctor(indexed_datum)(indexed_datum const & that)(
  61. requires copy_constructible<T>)
  62. {
  63. std::uninitialized_copy_n(that.data_, N, data_);
  64. }
  65. // \pre Requires distance(first, last) <= N
  66. // \pre Requires default_constructible<T> || distance(first, last) == N
  67. template(typename I, typename S)(
  68. requires sentinel_for<S, I> AND input_iterator<I> AND
  69. constructible_from<T, iter_reference_t<I>>)
  70. indexed_datum(I first, S last)
  71. {
  72. T * p = detail::uninitialized_copy(first, last, data_);
  73. this->fill_default_(p, meta::bool_<default_constructible<T>>{});
  74. }
  75. // \pre Requires distance(r) <= N
  76. // \pre Requires default_constructible<T> || distance(r) == N
  77. template(typename R)(
  78. requires input_range<R> AND constructible_from<T, range_reference_t<R>>)
  79. explicit indexed_datum(R && r)
  80. : indexed_datum{ranges::begin(r), ranges::end(r)}
  81. {}
  82. CPP_member
  83. auto operator=(indexed_datum && that) //
  84. -> CPP_ret(indexed_datum &)(
  85. requires assignable_from<T &, T>)
  86. {
  87. ranges::move(that.data_, data_);
  88. return *this;
  89. }
  90. CPP_member
  91. auto operator=(indexed_datum const & that) //
  92. -> CPP_ret(indexed_datum &)(
  93. requires assignable_from<T &, T const &>)
  94. {
  95. ranges::copy(that.data_, data_);
  96. return *this;
  97. }
  98. // \pre Requires ranges::distance(r) <= N
  99. template(typename R)(
  100. requires input_range<R> AND assignable_from<T &, range_reference_t<R>>)
  101. indexed_datum & operator=(R && r)
  102. {
  103. ranges::copy(r, data_);
  104. return *this;
  105. }
  106. constexpr auto ref()
  107. {
  108. return indexed_element<T(&)[N], Index::value>{data_};
  109. }
  110. constexpr auto ref() const
  111. {
  112. return indexed_element<T const(&)[N], Index::value>{data_};
  113. }
  114. constexpr T (&get() noexcept)[N]
  115. {
  116. return data_;
  117. }
  118. constexpr T const (&get() const noexcept)[N]
  119. {
  120. return data_;
  121. }
  122. };
  123. } // namespace detail
  124. /// \endcond
  125. } // namespace ranges
  126. #include <range/v3/detail/epilogue.hpp>
  127. #endif