view_or_value.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Copyright 2015 MongoDB Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #pragma once
  15. #include <type_traits>
  16. #include <bsoncxx/stdx/optional.hpp>
  17. #include <bsoncxx/config/prelude.hpp>
  18. namespace bsoncxx {
  19. BSONCXX_INLINE_NAMESPACE_BEGIN
  20. ///
  21. /// Class representing a view-or-value variant type.
  22. ///
  23. template <typename View, typename Value>
  24. class view_or_value {
  25. public:
  26. using view_type = View;
  27. using value_type = Value;
  28. ///
  29. /// Class View must be constructible from an instance of class Value.
  30. ///
  31. static_assert(std::is_constructible<View, Value>::value,
  32. "View type must be constructible from a Value");
  33. ///
  34. /// Class View must be default constructible.
  35. ///
  36. static_assert(std::is_default_constructible<View>::value,
  37. "View type must be default constructible");
  38. ///
  39. /// Default-constructs a view_or_value. This is equivalent to constructing a
  40. /// view_or_value with a default-constructed View.
  41. ///
  42. BSONCXX_INLINE view_or_value() = default;
  43. ///
  44. /// Construct a view_or_value from a View. When constructed with a View,
  45. /// this object is non-owning. The Value underneath the given View must outlive this object.
  46. ///
  47. /// @param view
  48. /// A non-owning View.
  49. ///
  50. BSONCXX_INLINE view_or_value(View view) : _view{view} {}
  51. ///
  52. /// Constructs a view_or_value from a Value type. This object owns the passed-in Value.
  53. ///
  54. /// @param value
  55. /// A Value type.
  56. ///
  57. BSONCXX_INLINE view_or_value(Value&& value) : _value(std::move(value)), _view(*_value) {}
  58. ///
  59. /// Construct a view_or_value from a copied view_or_value.
  60. ///
  61. BSONCXX_INLINE view_or_value(const view_or_value& other)
  62. : _value(other._value), _view(_value ? *_value : other._view) {}
  63. ///
  64. /// Assign to this view_or_value from a copied view_or_value.
  65. ///
  66. BSONCXX_INLINE view_or_value& operator=(const view_or_value& other) {
  67. _value = other._value;
  68. _view = _value ? *_value : other._view;
  69. return *this;
  70. }
  71. ///
  72. /// Construct a view_or_value from a moved-in view_or_value.
  73. ///
  74. /// TODO CXX-800: Create a noexcept expression to check the conditions that must be met.
  75. BSONCXX_INLINE view_or_value(view_or_value &&other) noexcept
  76. : _value{std::move(other._value)},
  77. _view(_value ? *_value : std::move(other._view)) {
  78. other._view = View();
  79. other._value = stdx::nullopt;
  80. }
  81. ///
  82. /// Assign to this view_or_value from a moved-in view_or_value.
  83. ///
  84. /// TODO CXX-800: Create a noexcept expression to check the conditions that must be met.
  85. BSONCXX_INLINE view_or_value& operator=(view_or_value&& other) noexcept {
  86. _value = std::move(other._value);
  87. _view = _value ? *_value : std::move(other._view);
  88. other._view = View();
  89. other._value = stdx::nullopt;
  90. return *this;
  91. }
  92. ///
  93. /// Return whether or not this view_or_value owns an underlying Value.
  94. ///
  95. /// @return bool Whether we are owning.
  96. ///
  97. BSONCXX_INLINE bool is_owning() const noexcept {
  98. return static_cast<bool>(_value);
  99. }
  100. ///
  101. /// This type may be used as a View.
  102. ///
  103. /// @return a View into this view_or_value.
  104. ///
  105. BSONCXX_INLINE operator View() const {
  106. return _view;
  107. }
  108. ///
  109. /// Get a View for the type.
  110. ///
  111. /// @return a View into this view_or_value.
  112. ///
  113. BSONCXX_INLINE const View& view() const {
  114. return _view;
  115. }
  116. private:
  117. stdx::optional<Value> _value;
  118. View _view;
  119. };
  120. ///
  121. /// @{
  122. ///
  123. /// Compare view_or_value objects for (in)-equality
  124. ///
  125. /// @relates: view_or_value
  126. ///
  127. template <typename View, typename Value>
  128. BSONCXX_INLINE bool operator==(const view_or_value<View, Value>& lhs,
  129. const view_or_value<View, Value>& rhs) {
  130. return lhs.view() == rhs.view();
  131. }
  132. template <typename View, typename Value>
  133. BSONCXX_INLINE bool operator!=(const view_or_value<View, Value>& lhs,
  134. const view_or_value<View, Value>& rhs) {
  135. return !(lhs == rhs);
  136. }
  137. ///
  138. /// @}
  139. ///
  140. ///
  141. /// @{
  142. ///
  143. /// Mixed (in)-equality operators for view_or_value against View or Value types
  144. ///
  145. /// @relates view_or_value
  146. ///
  147. template <typename View, typename Value>
  148. BSONCXX_INLINE bool operator==(const view_or_value<View, Value>& lhs, View rhs) {
  149. return lhs.view() == rhs;
  150. }
  151. template <typename View, typename Value>
  152. BSONCXX_INLINE bool operator==(View lhs, const view_or_value<View, Value>& rhs) {
  153. return rhs == lhs;
  154. }
  155. template <typename View, typename Value>
  156. BSONCXX_INLINE bool operator!=(const view_or_value<View, Value>& lhs, View rhs) {
  157. return !(lhs == rhs);
  158. }
  159. template <typename View, typename Value>
  160. BSONCXX_INLINE bool operator!=(View lhs, const view_or_value<View, Value>& rhs) {
  161. return !(rhs == lhs);
  162. }
  163. template <typename View, typename Value>
  164. BSONCXX_INLINE bool operator==(const view_or_value<View, Value>& lhs, const Value& rhs) {
  165. return lhs.view() == View(rhs);
  166. }
  167. template <typename View, typename Value>
  168. BSONCXX_INLINE bool operator==(const Value& lhs, const view_or_value<View, Value>& rhs) {
  169. return rhs == lhs;
  170. }
  171. template <typename View, typename Value>
  172. BSONCXX_INLINE bool operator!=(const view_or_value<View, Value>& lhs, const Value& rhs) {
  173. return !(lhs == rhs);
  174. }
  175. template <typename View, typename Value>
  176. BSONCXX_INLINE bool operator!=(const Value& lhs, const view_or_value<View, Value>& rhs) {
  177. return !(rhs == lhs);
  178. }
  179. ///
  180. /// @}
  181. ///
  182. BSONCXX_INLINE_NAMESPACE_END
  183. } // namespace bsoncxx
  184. #include <bsoncxx/config/postlude.hpp>