| 1 | // Copyright 2018 The Abseil Authors. |
| 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 | // https://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 | // |
| 15 | // ----------------------------------------------------------------------------- |
| 16 | // variant.h |
| 17 | // ----------------------------------------------------------------------------- |
| 18 | // |
| 19 | // This header file defines an `absl::variant` type for holding a type-safe |
| 20 | // value of some prescribed set of types (noted as alternative types), and |
| 21 | // associated functions for managing variants. |
| 22 | // |
| 23 | // The `absl::variant` type is a form of type-safe union. An `absl::variant` |
| 24 | // should always hold a value of one of its alternative types (except in the |
| 25 | // "valueless by exception state" -- see below). A default-constructed |
| 26 | // `absl::variant` will hold the value of its first alternative type, provided |
| 27 | // it is default-constructable. |
| 28 | // |
| 29 | // In exceptional cases due to error, an `absl::variant` can hold no |
| 30 | // value (known as a "valueless by exception" state), though this is not the |
| 31 | // norm. |
| 32 | // |
| 33 | // As with `absl::optional`, an `absl::variant` -- when it holds a value -- |
| 34 | // allocates a value of that type directly within the `variant` itself; it |
| 35 | // cannot hold a reference, array, or the type `void`; it can, however, hold a |
| 36 | // pointer to externally managed memory. |
| 37 | // |
| 38 | // `absl::variant` is a C++11 compatible version of the C++17 `std::variant` |
| 39 | // abstraction and is designed to be a drop-in replacement for code compliant |
| 40 | // with C++17. |
| 41 | |
| 42 | #ifndef ABSL_TYPES_VARIANT_H_ |
| 43 | #define ABSL_TYPES_VARIANT_H_ |
| 44 | |
| 45 | #include "absl/base/config.h" |
| 46 | #include "absl/utility/utility.h" |
| 47 | |
| 48 | #ifdef ABSL_HAVE_STD_VARIANT |
| 49 | |
| 50 | #include <variant> // IWYU pragma: export |
| 51 | |
| 52 | namespace absl { |
| 53 | using std::bad_variant_access; |
| 54 | using std::get; |
| 55 | using std::get_if; |
| 56 | using std::holds_alternative; |
| 57 | using std::monostate; |
| 58 | using std::variant; |
| 59 | using std::variant_alternative; |
| 60 | using std::variant_alternative_t; |
| 61 | using std::variant_npos; |
| 62 | using std::variant_size; |
| 63 | using std::variant_size_v; |
| 64 | using std::visit; |
| 65 | } // namespace absl |
| 66 | |
| 67 | #else // ABSL_HAVE_STD_VARIANT |
| 68 | |
| 69 | #include <functional> |
| 70 | #include <new> |
| 71 | #include <type_traits> |
| 72 | #include <utility> |
| 73 | |
| 74 | #include "absl/base/macros.h" |
| 75 | #include "absl/base/port.h" |
| 76 | #include "absl/meta/type_traits.h" |
| 77 | #include "absl/types/internal/variant.h" |
| 78 | |
| 79 | namespace absl { |
| 80 | |
| 81 | // ----------------------------------------------------------------------------- |
| 82 | // absl::variant |
| 83 | // ----------------------------------------------------------------------------- |
| 84 | // |
| 85 | // An `absl::variant` type is a form of type-safe union. An `absl::variant` -- |
| 86 | // except in exceptional cases -- always holds a value of one of its alternative |
| 87 | // types. |
| 88 | // |
| 89 | // Example: |
| 90 | // |
| 91 | // // Construct a variant that holds either an integer or a std::string and |
| 92 | // // assign it to a std::string. |
| 93 | // absl::variant<int, std::string> v = std::string("abc"); |
| 94 | // |
| 95 | // // A default-contructed variant will hold a value-initialized value of |
| 96 | // // the first alternative type. |
| 97 | // auto a = absl::variant<int, std::string>(); // Holds an int of value '0'. |
| 98 | // |
| 99 | // // variants are assignable. |
| 100 | // |
| 101 | // // copy assignment |
| 102 | // auto v1 = absl::variant<int, std::string>("abc"); |
| 103 | // auto v2 = absl::variant<int, std::string>(10); |
| 104 | // v2 = v1; // copy assign |
| 105 | // |
| 106 | // // move assignment |
| 107 | // auto v1 = absl::variant<int, std::string>("abc"); |
| 108 | // v1 = absl::variant<int, std::string>(10); |
| 109 | // |
| 110 | // // assignment through type conversion |
| 111 | // a = 128; // variant contains int |
| 112 | // a = "128"; // variant contains std::string |
| 113 | // |
| 114 | // An `absl::variant` holding a value of one of its alternative types `T` holds |
| 115 | // an allocation of `T` directly within the variant itself. An `absl::variant` |
| 116 | // is not allowed to allocate additional storage, such as dynamic memory, to |
| 117 | // allocate the contained value. The contained value shall be allocated in a |
| 118 | // region of the variant storage suitably aligned for all alternative types. |
| 119 | template <typename... Ts> |
| 120 | class variant; |
| 121 | |
| 122 | // swap() |
| 123 | // |
| 124 | // Swaps two `absl::variant` values. This function is equivalent to `v.swap(w)` |
| 125 | // where `v` and `w` are `absl::variant` types. |
| 126 | // |
| 127 | // Note that this function requires all alternative types to be both swappable |
| 128 | // and move-constructible, because any two variants may refer to either the same |
| 129 | // type (in which case, they will be swapped) or to two different types (in |
| 130 | // which case the values will need to be moved). |
| 131 | // |
| 132 | template < |
| 133 | typename... Ts, |
| 134 | absl::enable_if_t< |
| 135 | absl::conjunction<std::is_move_constructible<Ts>..., |
| 136 | type_traits_internal::IsSwappable<Ts>...>::value, |
| 137 | int> = 0> |
| 138 | void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) { |
| 139 | v.swap(w); |
| 140 | } |
| 141 | |
| 142 | // variant_size |
| 143 | // |
| 144 | // Returns the number of alternative types available for a given `absl::variant` |
| 145 | // type as a compile-time constant expression. As this is a class template, it |
| 146 | // is not generally useful for accessing the number of alternative types of |
| 147 | // any given `absl::variant` instance. |
| 148 | // |
| 149 | // Example: |
| 150 | // |
| 151 | // auto a = absl::variant<int, std::string>; |
| 152 | // constexpr int num_types = |
| 153 | // absl::variant_size<absl::variant<int, std::string>>(); |
| 154 | // |
| 155 | // // You can also use the member constant `value`. |
| 156 | // constexpr int num_types = |
| 157 | // absl::variant_size<absl::variant<int, std::string>>::value; |
| 158 | // |
| 159 | // // `absl::variant_size` is more valuable for use in generic code: |
| 160 | // template <typename Variant> |
| 161 | // constexpr bool IsVariantMultivalue() { |
| 162 | // return absl::variant_size<Variant>() > 1; |
| 163 | // } |
| 164 | // |
| 165 | // Note that the set of cv-qualified specializations of `variant_size` are |
| 166 | // provided to ensure that those specializations compile (especially when passed |
| 167 | // within template logic). |
| 168 | template <class T> |
| 169 | struct variant_size; |
| 170 | |
| 171 | template <class... Ts> |
| 172 | struct variant_size<variant<Ts...>> |
| 173 | : std::integral_constant<std::size_t, sizeof...(Ts)> {}; |
| 174 | |
| 175 | // Specialization of `variant_size` for const qualified variants. |
| 176 | template <class T> |
| 177 | struct variant_size<const T> : variant_size<T>::type {}; |
| 178 | |
| 179 | // Specialization of `variant_size` for volatile qualified variants. |
| 180 | template <class T> |
| 181 | struct variant_size<volatile T> : variant_size<T>::type {}; |
| 182 | |
| 183 | // Specialization of `variant_size` for const volatile qualified variants. |
| 184 | template <class T> |
| 185 | struct variant_size<const volatile T> : variant_size<T>::type {}; |
| 186 | |
| 187 | // variant_alternative |
| 188 | // |
| 189 | // Returns the alternative type for a given `absl::variant` at the passed |
| 190 | // index value as a compile-time constant expression. As this is a class |
| 191 | // template resulting in a type, it is not useful for access of the run-time |
| 192 | // value of any given `absl::variant` variable. |
| 193 | // |
| 194 | // Example: |
| 195 | // |
| 196 | // // The type of the 0th alternative is "int". |
| 197 | // using alternative_type_0 |
| 198 | // = absl::variant_alternative<0, absl::variant<int, std::string>>::type; |
| 199 | // |
| 200 | // static_assert(std::is_same<alternative_type_0, int>::value, ""); |
| 201 | // |
| 202 | // // `absl::variant_alternative` is more valuable for use in generic code: |
| 203 | // template <typename Variant> |
| 204 | // constexpr bool IsFirstElementTrivial() { |
| 205 | // return std::is_trivial_v<variant_alternative<0, Variant>::type>; |
| 206 | // } |
| 207 | // |
| 208 | // Note that the set of cv-qualified specializations of `variant_alternative` |
| 209 | // are provided to ensure that those specializations compile (especially when |
| 210 | // passed within template logic). |
| 211 | template <std::size_t I, class T> |
| 212 | struct variant_alternative; |
| 213 | |
| 214 | template <std::size_t I, class... Types> |
| 215 | struct variant_alternative<I, variant<Types...>> { |
| 216 | using type = |
| 217 | variant_internal::VariantAlternativeSfinaeT<I, variant<Types...>>; |
| 218 | }; |
| 219 | |
| 220 | // Specialization of `variant_alternative` for const qualified variants. |
| 221 | template <std::size_t I, class T> |
| 222 | struct variant_alternative<I, const T> { |
| 223 | using type = const typename variant_alternative<I, T>::type; |
| 224 | }; |
| 225 | |
| 226 | // Specialization of `variant_alternative` for volatile qualified variants. |
| 227 | template <std::size_t I, class T> |
| 228 | struct variant_alternative<I, volatile T> { |
| 229 | using type = volatile typename variant_alternative<I, T>::type; |
| 230 | }; |
| 231 | |
| 232 | // Specialization of `variant_alternative` for const volatile qualified |
| 233 | // variants. |
| 234 | template <std::size_t I, class T> |
| 235 | struct variant_alternative<I, const volatile T> { |
| 236 | using type = const volatile typename variant_alternative<I, T>::type; |
| 237 | }; |
| 238 | |
| 239 | // Template type alias for variant_alternative<I, T>::type. |
| 240 | // |
| 241 | // Example: |
| 242 | // |
| 243 | // using alternative_type_0 |
| 244 | // = absl::variant_alternative_t<0, absl::variant<int, std::string>>; |
| 245 | // static_assert(std::is_same<alternative_type_0, int>::value, ""); |
| 246 | template <std::size_t I, class T> |
| 247 | using variant_alternative_t = typename variant_alternative<I, T>::type; |
| 248 | |
| 249 | // holds_alternative() |
| 250 | // |
| 251 | // Checks whether the given variant currently holds a given alternative type, |
| 252 | // returning `true` if so. |
| 253 | // |
| 254 | // Example: |
| 255 | // |
| 256 | // absl::variant<int, std::string> foo = 42; |
| 257 | // if (absl::holds_alternative<int>(foo)) { |
| 258 | // std::cout << "The variant holds an integer"; |
| 259 | // } |
| 260 | template <class T, class... Types> |
| 261 | constexpr bool holds_alternative(const variant<Types...>& v) noexcept { |
| 262 | static_assert( |
| 263 | variant_internal::UnambiguousIndexOfImpl<variant<Types...>, T, |
| 264 | 0>::value != sizeof...(Types), |
| 265 | "The type T must occur exactly once in Types..." ); |
| 266 | return v.index() == |
| 267 | variant_internal::UnambiguousIndexOf<variant<Types...>, T>::value; |
| 268 | } |
| 269 | |
| 270 | // get() |
| 271 | // |
| 272 | // Returns a reference to the value currently within a given variant, using |
| 273 | // either a unique alternative type amongst the variant's set of alternative |
| 274 | // types, or the variant's index value. Attempting to get a variant's value |
| 275 | // using a type that is not unique within the variant's set of alternative types |
| 276 | // is a compile-time error. If the index of the alternative being specified is |
| 277 | // different from the index of the alternative that is currently stored, throws |
| 278 | // `absl::bad_variant_access`. |
| 279 | // |
| 280 | // Example: |
| 281 | // |
| 282 | // auto a = absl::variant<int, std::string>; |
| 283 | // |
| 284 | // // Get the value by type (if unique). |
| 285 | // int i = absl::get<int>(a); |
| 286 | // |
| 287 | // auto b = absl::variant<int, int>; |
| 288 | // |
| 289 | // // Getting the value by a type that is not unique is ill-formed. |
| 290 | // int j = absl::get<int>(b); // Compile Error! |
| 291 | // |
| 292 | // // Getting value by index not ambiguous and allowed. |
| 293 | // int k = absl::get<1>(b); |
| 294 | |
| 295 | // Overload for getting a variant's lvalue by type. |
| 296 | template <class T, class... Types> |
| 297 | constexpr T& get(variant<Types...>& v) { // NOLINT |
| 298 | return variant_internal::VariantCoreAccess::CheckedAccess< |
| 299 | variant_internal::IndexOf<T, Types...>::value>(v); |
| 300 | } |
| 301 | |
| 302 | // Overload for getting a variant's rvalue by type. |
| 303 | // Note: `absl::move()` is required to allow use of constexpr in C++11. |
| 304 | template <class T, class... Types> |
| 305 | constexpr T&& get(variant<Types...>&& v) { |
| 306 | return variant_internal::VariantCoreAccess::CheckedAccess< |
| 307 | variant_internal::IndexOf<T, Types...>::value>(absl::move(v)); |
| 308 | } |
| 309 | |
| 310 | // Overload for getting a variant's const lvalue by type. |
| 311 | template <class T, class... Types> |
| 312 | constexpr const T& get(const variant<Types...>& v) { |
| 313 | return variant_internal::VariantCoreAccess::CheckedAccess< |
| 314 | variant_internal::IndexOf<T, Types...>::value>(v); |
| 315 | } |
| 316 | |
| 317 | // Overload for getting a variant's const rvalue by type. |
| 318 | // Note: `absl::move()` is required to allow use of constexpr in C++11. |
| 319 | template <class T, class... Types> |
| 320 | constexpr const T&& get(const variant<Types...>&& v) { |
| 321 | return variant_internal::VariantCoreAccess::CheckedAccess< |
| 322 | variant_internal::IndexOf<T, Types...>::value>(absl::move(v)); |
| 323 | } |
| 324 | |
| 325 | // Overload for getting a variant's lvalue by index. |
| 326 | template <std::size_t I, class... Types> |
| 327 | constexpr variant_alternative_t<I, variant<Types...>>& get( |
| 328 | variant<Types...>& v) { // NOLINT |
| 329 | return variant_internal::VariantCoreAccess::CheckedAccess<I>(v); |
| 330 | } |
| 331 | |
| 332 | // Overload for getting a variant's rvalue by index. |
| 333 | // Note: `absl::move()` is required to allow use of constexpr in C++11. |
| 334 | template <std::size_t I, class... Types> |
| 335 | constexpr variant_alternative_t<I, variant<Types...>>&& get( |
| 336 | variant<Types...>&& v) { |
| 337 | return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v)); |
| 338 | } |
| 339 | |
| 340 | // Overload for getting a variant's const lvalue by index. |
| 341 | template <std::size_t I, class... Types> |
| 342 | constexpr const variant_alternative_t<I, variant<Types...>>& get( |
| 343 | const variant<Types...>& v) { |
| 344 | return variant_internal::VariantCoreAccess::CheckedAccess<I>(v); |
| 345 | } |
| 346 | |
| 347 | // Overload for getting a variant's const rvalue by index. |
| 348 | // Note: `absl::move()` is required to allow use of constexpr in C++11. |
| 349 | template <std::size_t I, class... Types> |
| 350 | constexpr const variant_alternative_t<I, variant<Types...>>&& get( |
| 351 | const variant<Types...>&& v) { |
| 352 | return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v)); |
| 353 | } |
| 354 | |
| 355 | // get_if() |
| 356 | // |
| 357 | // Returns a pointer to the value currently stored within a given variant, if |
| 358 | // present, using either a unique alternative type amongst the variant's set of |
| 359 | // alternative types, or the variant's index value. If such a value does not |
| 360 | // exist, returns `nullptr`. |
| 361 | // |
| 362 | // As with `get`, attempting to get a variant's value using a type that is not |
| 363 | // unique within the variant's set of alternative types is a compile-time error. |
| 364 | |
| 365 | // Overload for getting a pointer to the value stored in the given variant by |
| 366 | // index. |
| 367 | template <std::size_t I, class... Types> |
| 368 | constexpr absl::add_pointer_t<variant_alternative_t<I, variant<Types...>>> |
| 369 | get_if(variant<Types...>* v) noexcept { |
| 370 | return (v != nullptr && v->index() == I) |
| 371 | ? std::addressof( |
| 372 | variant_internal::VariantCoreAccess::Access<I>(*v)) |
| 373 | : nullptr; |
| 374 | } |
| 375 | |
| 376 | // Overload for getting a pointer to the const value stored in the given |
| 377 | // variant by index. |
| 378 | template <std::size_t I, class... Types> |
| 379 | constexpr absl::add_pointer_t<const variant_alternative_t<I, variant<Types...>>> |
| 380 | get_if(const variant<Types...>* v) noexcept { |
| 381 | return (v != nullptr && v->index() == I) |
| 382 | ? std::addressof( |
| 383 | variant_internal::VariantCoreAccess::Access<I>(*v)) |
| 384 | : nullptr; |
| 385 | } |
| 386 | |
| 387 | // Overload for getting a pointer to the value stored in the given variant by |
| 388 | // type. |
| 389 | template <class T, class... Types> |
| 390 | constexpr absl::add_pointer_t<T> get_if(variant<Types...>* v) noexcept { |
| 391 | return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v); |
| 392 | } |
| 393 | |
| 394 | // Overload for getting a pointer to the const value stored in the given variant |
| 395 | // by type. |
| 396 | template <class T, class... Types> |
| 397 | constexpr absl::add_pointer_t<const T> get_if( |
| 398 | const variant<Types...>* v) noexcept { |
| 399 | return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v); |
| 400 | } |
| 401 | |
| 402 | // visit() |
| 403 | // |
| 404 | // Calls a provided functor on a given set of variants. `absl::visit()` is |
| 405 | // commonly used to conditionally inspect the state of a given variant (or set |
| 406 | // of variants). |
| 407 | // |
| 408 | // The functor must return the same type when called with any of the variants' |
| 409 | // alternatives. |
| 410 | // |
| 411 | // Example: |
| 412 | // |
| 413 | // // Define a visitor functor |
| 414 | // struct GetVariant { |
| 415 | // template<typename T> |
| 416 | // void operator()(const T& i) const { |
| 417 | // std::cout << "The variant's value is: " << i; |
| 418 | // } |
| 419 | // }; |
| 420 | // |
| 421 | // // Declare our variant, and call `absl::visit()` on it. |
| 422 | // // Note that `GetVariant()` returns void in either case. |
| 423 | // absl::variant<int, std::string> foo = std::string("foo"); |
| 424 | // GetVariant visitor; |
| 425 | // absl::visit(visitor, foo); // Prints `The variant's value is: foo' |
| 426 | template <typename Visitor, typename... Variants> |
| 427 | variant_internal::VisitResult<Visitor, Variants...> visit(Visitor&& vis, |
| 428 | Variants&&... vars) { |
| 429 | return variant_internal:: |
| 430 | VisitIndices<variant_size<absl::decay_t<Variants> >::value...>::Run( |
| 431 | variant_internal::PerformVisitation<Visitor, Variants...>{ |
| 432 | std::forward_as_tuple(absl::forward<Variants>(vars)...), |
| 433 | absl::forward<Visitor>(vis)}, |
| 434 | vars.index()...); |
| 435 | } |
| 436 | |
| 437 | // monostate |
| 438 | // |
| 439 | // The monostate class serves as a first alternative type for a variant for |
| 440 | // which the first variant type is otherwise not default-constructible. |
| 441 | struct monostate {}; |
| 442 | |
| 443 | // `absl::monostate` Relational Operators |
| 444 | |
| 445 | constexpr bool operator<(monostate, monostate) noexcept { return false; } |
| 446 | constexpr bool operator>(monostate, monostate) noexcept { return false; } |
| 447 | constexpr bool operator<=(monostate, monostate) noexcept { return true; } |
| 448 | constexpr bool operator>=(monostate, monostate) noexcept { return true; } |
| 449 | constexpr bool operator==(monostate, monostate) noexcept { return true; } |
| 450 | constexpr bool operator!=(monostate, monostate) noexcept { return false; } |
| 451 | |
| 452 | |
| 453 | //------------------------------------------------------------------------------ |
| 454 | // `absl::variant` Template Definition |
| 455 | //------------------------------------------------------------------------------ |
| 456 | template <typename T0, typename... Tn> |
| 457 | class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> { |
| 458 | static_assert(absl::conjunction<std::is_object<T0>, |
| 459 | std::is_object<Tn>...>::value, |
| 460 | "Attempted to instantiate a variant containing a non-object " |
| 461 | "type." ); |
| 462 | // Intentionally not qualifying `negation` with `absl::` to work around a bug |
| 463 | // in MSVC 2015 with inline namespace and variadic template. |
| 464 | static_assert(absl::conjunction<negation<std::is_array<T0> >, |
| 465 | negation<std::is_array<Tn> >...>::value, |
| 466 | "Attempted to instantiate a variant containing an array type." ); |
| 467 | static_assert(absl::conjunction<std::is_nothrow_destructible<T0>, |
| 468 | std::is_nothrow_destructible<Tn>...>::value, |
| 469 | "Attempted to instantiate a variant containing a non-nothrow " |
| 470 | "destructible type." ); |
| 471 | |
| 472 | friend struct variant_internal::VariantCoreAccess; |
| 473 | |
| 474 | private: |
| 475 | using Base = variant_internal::VariantBase<T0, Tn...>; |
| 476 | |
| 477 | public: |
| 478 | // Constructors |
| 479 | |
| 480 | // Constructs a variant holding a default-initialized value of the first |
| 481 | // alternative type. |
| 482 | constexpr variant() /*noexcept(see 111above)*/ = default; |
| 483 | |
| 484 | // Copy constructor, standard semantics |
| 485 | variant(const variant& other) = default; |
| 486 | |
| 487 | // Move constructor, standard semantics |
| 488 | variant(variant&& other) /*noexcept(see above)*/ = default; |
| 489 | |
| 490 | // Constructs a variant of an alternative type specified by overload |
| 491 | // resolution of the provided forwarding arguments through |
| 492 | // direct-initialization. |
| 493 | // |
| 494 | // Note: If the selected constructor is a constexpr constructor, this |
| 495 | // constructor shall be a constexpr constructor. |
| 496 | // |
| 497 | // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html |
| 498 | // has been voted passed the design phase in the C++ standard meeting in Mar |
| 499 | // 2018. It will be implemented and integrated into `absl::variant`. |
| 500 | template < |
| 501 | class T, |
| 502 | std::size_t I = std::enable_if< |
| 503 | variant_internal::IsNeitherSelfNorInPlace<variant, |
| 504 | absl::decay_t<T>>::value, |
| 505 | variant_internal::IndexOfConstructedType<variant, T>>::type::value, |
| 506 | class Tj = absl::variant_alternative_t<I, variant>, |
| 507 | absl::enable_if_t<std::is_constructible<Tj, T>::value>* = |
| 508 | nullptr> |
| 509 | constexpr variant(T&& t) noexcept(std::is_nothrow_constructible<Tj, T>::value) |
| 510 | : Base(variant_internal::EmplaceTag<I>(), absl::forward<T>(t)) {} |
| 511 | |
| 512 | // Constructs a variant of an alternative type from the arguments through |
| 513 | // direct-initialization. |
| 514 | // |
| 515 | // Note: If the selected constructor is a constexpr constructor, this |
| 516 | // constructor shall be a constexpr constructor. |
| 517 | template <class T, class... Args, |
| 518 | typename std::enable_if<std::is_constructible< |
| 519 | variant_internal::UnambiguousTypeOfT<variant, T>, |
| 520 | Args...>::value>::type* = nullptr> |
| 521 | constexpr explicit variant(in_place_type_t<T>, Args&&... args) |
| 522 | : Base(variant_internal::EmplaceTag< |
| 523 | variant_internal::UnambiguousIndexOf<variant, T>::value>(), |
| 524 | absl::forward<Args>(args)...) {} |
| 525 | |
| 526 | // Constructs a variant of an alternative type from an initializer list |
| 527 | // and other arguments through direct-initialization. |
| 528 | // |
| 529 | // Note: If the selected constructor is a constexpr constructor, this |
| 530 | // constructor shall be a constexpr constructor. |
| 531 | template <class T, class U, class... Args, |
| 532 | typename std::enable_if<std::is_constructible< |
| 533 | variant_internal::UnambiguousTypeOfT<variant, T>, |
| 534 | std::initializer_list<U>&, Args...>::value>::type* = nullptr> |
| 535 | constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U> il, |
| 536 | Args&&... args) |
| 537 | : Base(variant_internal::EmplaceTag< |
| 538 | variant_internal::UnambiguousIndexOf<variant, T>::value>(), |
| 539 | il, absl::forward<Args>(args)...) {} |
| 540 | |
| 541 | // Constructs a variant of an alternative type from a provided index, |
| 542 | // through value-initialization using the provided forwarded arguments. |
| 543 | template <std::size_t I, class... Args, |
| 544 | typename std::enable_if<std::is_constructible< |
| 545 | variant_internal::VariantAlternativeSfinaeT<I, variant>, |
| 546 | Args...>::value>::type* = nullptr> |
| 547 | constexpr explicit variant(in_place_index_t<I>, Args&&... args) |
| 548 | : Base(variant_internal::EmplaceTag<I>(), absl::forward<Args>(args)...) {} |
| 549 | |
| 550 | // Constructs a variant of an alternative type from a provided index, |
| 551 | // through value-initialization of an initializer list and the provided |
| 552 | // forwarded arguments. |
| 553 | template <std::size_t I, class U, class... Args, |
| 554 | typename std::enable_if<std::is_constructible< |
| 555 | variant_internal::VariantAlternativeSfinaeT<I, variant>, |
| 556 | std::initializer_list<U>&, Args...>::value>::type* = nullptr> |
| 557 | constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U> il, |
| 558 | Args&&... args) |
| 559 | : Base(variant_internal::EmplaceTag<I>(), il, |
| 560 | absl::forward<Args>(args)...) {} |
| 561 | |
| 562 | // Destructors |
| 563 | |
| 564 | // Destroys the variant's currently contained value, provided that |
| 565 | // `absl::valueless_by_exception()` is false. |
| 566 | ~variant() = default; |
| 567 | |
| 568 | // Assignment Operators |
| 569 | |
| 570 | // Copy assignment operator |
| 571 | variant& operator=(const variant& other) = default; |
| 572 | |
| 573 | // Move assignment operator |
| 574 | variant& operator=(variant&& other) /*noexcept(see above)*/ = default; |
| 575 | |
| 576 | // Converting assignment operator |
| 577 | // |
| 578 | // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html |
| 579 | // has been voted passed the design phase in the C++ standard meeting in Mar |
| 580 | // 2018. It will be implemented and integrated into `absl::variant`. |
| 581 | template < |
| 582 | class T, |
| 583 | std::size_t I = std::enable_if< |
| 584 | !std::is_same<absl::decay_t<T>, variant>::value, |
| 585 | variant_internal::IndexOfConstructedType<variant, T>>::type::value, |
| 586 | class Tj = absl::variant_alternative_t<I, variant>, |
| 587 | typename std::enable_if<std::is_assignable<Tj&, T>::value && |
| 588 | std::is_constructible<Tj, T>::value>::type* = |
| 589 | nullptr> |
| 590 | variant& operator=(T&& t) noexcept( |
| 591 | std::is_nothrow_assignable<Tj&, T>::value&& |
| 592 | std::is_nothrow_constructible<Tj, T>::value) { |
| 593 | variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run( |
| 594 | variant_internal::VariantCoreAccess::MakeConversionAssignVisitor( |
| 595 | this, absl::forward<T>(t)), |
| 596 | index()); |
| 597 | |
| 598 | return *this; |
| 599 | } |
| 600 | |
| 601 | |
| 602 | // emplace() Functions |
| 603 | |
| 604 | // Constructs a value of the given alternative type T within the variant. |
| 605 | // |
| 606 | // Example: |
| 607 | // |
| 608 | // absl::variant<std::vector<int>, int, std::string> v; |
| 609 | // v.emplace<int>(99); |
| 610 | // v.emplace<std::string>("abc"); |
| 611 | template < |
| 612 | class T, class... Args, |
| 613 | typename std::enable_if<std::is_constructible< |
| 614 | absl::variant_alternative_t< |
| 615 | variant_internal::UnambiguousIndexOf<variant, T>::value, variant>, |
| 616 | Args...>::value>::type* = nullptr> |
| 617 | T& emplace(Args&&... args) { |
| 618 | return variant_internal::VariantCoreAccess::Replace< |
| 619 | variant_internal::UnambiguousIndexOf<variant, T>::value>( |
| 620 | this, absl::forward<Args>(args)...); |
| 621 | } |
| 622 | |
| 623 | // Constructs a value of the given alternative type T within the variant using |
| 624 | // an initializer list. |
| 625 | // |
| 626 | // Example: |
| 627 | // |
| 628 | // absl::variant<std::vector<int>, int, std::string> v; |
| 629 | // v.emplace<std::vector<int>>({0, 1, 2}); |
| 630 | template < |
| 631 | class T, class U, class... Args, |
| 632 | typename std::enable_if<std::is_constructible< |
| 633 | absl::variant_alternative_t< |
| 634 | variant_internal::UnambiguousIndexOf<variant, T>::value, variant>, |
| 635 | std::initializer_list<U>&, Args...>::value>::type* = nullptr> |
| 636 | T& emplace(std::initializer_list<U> il, Args&&... args) { |
| 637 | return variant_internal::VariantCoreAccess::Replace< |
| 638 | variant_internal::UnambiguousIndexOf<variant, T>::value>( |
| 639 | this, il, absl::forward<Args>(args)...); |
| 640 | } |
| 641 | |
| 642 | // Destroys the current value of the variant (provided that |
| 643 | // `absl::valueless_by_exception()` is false, and constructs a new value at |
| 644 | // the given index. |
| 645 | // |
| 646 | // Example: |
| 647 | // |
| 648 | // absl::variant<std::vector<int>, int, int> v; |
| 649 | // v.emplace<1>(99); |
| 650 | // v.emplace<2>(98); |
| 651 | // v.emplace<int>(99); // Won't compile. 'int' isn't a unique type. |
| 652 | template <std::size_t I, class... Args, |
| 653 | typename std::enable_if< |
| 654 | std::is_constructible<absl::variant_alternative_t<I, variant>, |
| 655 | Args...>::value>::type* = nullptr> |
| 656 | absl::variant_alternative_t<I, variant>& emplace(Args&&... args) { |
| 657 | return variant_internal::VariantCoreAccess::Replace<I>( |
| 658 | this, absl::forward<Args>(args)...); |
| 659 | } |
| 660 | |
| 661 | // Destroys the current value of the variant (provided that |
| 662 | // `absl::valueless_by_exception()` is false, and constructs a new value at |
| 663 | // the given index using an initializer list and the provided arguments. |
| 664 | // |
| 665 | // Example: |
| 666 | // |
| 667 | // absl::variant<std::vector<int>, int, int> v; |
| 668 | // v.emplace<0>({0, 1, 2}); |
| 669 | template <std::size_t I, class U, class... Args, |
| 670 | typename std::enable_if<std::is_constructible< |
| 671 | absl::variant_alternative_t<I, variant>, |
| 672 | std::initializer_list<U>&, Args...>::value>::type* = nullptr> |
| 673 | absl::variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il, |
| 674 | Args&&... args) { |
| 675 | return variant_internal::VariantCoreAccess::Replace<I>( |
| 676 | this, il, absl::forward<Args>(args)...); |
| 677 | } |
| 678 | |
| 679 | // variant::valueless_by_exception() |
| 680 | // |
| 681 | // Returns false if and only if the variant currently holds a valid value. |
| 682 | constexpr bool valueless_by_exception() const noexcept { |
| 683 | return this->index_ == absl::variant_npos; |
| 684 | } |
| 685 | |
| 686 | // variant::index() |
| 687 | // |
| 688 | // Returns the index value of the variant's currently selected alternative |
| 689 | // type. |
| 690 | constexpr std::size_t index() const noexcept { return this->index_; } |
| 691 | |
| 692 | // variant::swap() |
| 693 | // |
| 694 | // Swaps the values of two variant objects. |
| 695 | // |
| 696 | void swap(variant& rhs) noexcept( |
| 697 | absl::conjunction< |
| 698 | std::is_nothrow_move_constructible<T0>, |
| 699 | std::is_nothrow_move_constructible<Tn>..., |
| 700 | type_traits_internal::IsNothrowSwappable<T0>, |
| 701 | type_traits_internal::IsNothrowSwappable<Tn>...>::value) { |
| 702 | return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run( |
| 703 | variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index()); |
| 704 | } |
| 705 | }; |
| 706 | |
| 707 | // We need a valid declaration of variant<> for SFINAE and overload resolution |
| 708 | // to work properly above, but we don't need a full declaration since this type |
| 709 | // will never be constructed. This declaration, though incomplete, suffices. |
| 710 | template <> |
| 711 | class variant<>; |
| 712 | |
| 713 | //------------------------------------------------------------------------------ |
| 714 | // Relational Operators |
| 715 | //------------------------------------------------------------------------------ |
| 716 | // |
| 717 | // If neither operand is in the `variant::valueless_by_exception` state: |
| 718 | // |
| 719 | // * If the index of both variants is the same, the relational operator |
| 720 | // returns the result of the corresponding relational operator for the |
| 721 | // corresponding alternative type. |
| 722 | // * If the index of both variants is not the same, the relational operator |
| 723 | // returns the result of that operation applied to the value of the left |
| 724 | // operand's index and the value of the right operand's index. |
| 725 | // * If at least one operand is in the valueless_by_exception state: |
| 726 | // - A variant in the valueless_by_exception state is only considered equal |
| 727 | // to another variant in the valueless_by_exception state. |
| 728 | // - If exactly one operand is in the valueless_by_exception state, the |
| 729 | // variant in the valueless_by_exception state is less than the variant |
| 730 | // that is not in the valueless_by_exception state. |
| 731 | // |
| 732 | // Note: The value 1 is added to each index in the relational comparisons such |
| 733 | // that the index corresponding to the valueless_by_exception state wraps around |
| 734 | // to 0 (the lowest value for the index type), and the remaining indices stay in |
| 735 | // the same relative order. |
| 736 | |
| 737 | // Equal-to operator |
| 738 | template <typename... Types> |
| 739 | constexpr variant_internal::RequireAllHaveEqualT<Types...> operator==( |
| 740 | const variant<Types...>& a, const variant<Types...>& b) { |
| 741 | return (a.index() == b.index()) && |
| 742 | variant_internal::VisitIndices<sizeof...(Types)>::Run( |
| 743 | variant_internal::EqualsOp<Types...>{&a, &b}, a.index()); |
| 744 | } |
| 745 | |
| 746 | // Not equal operator |
| 747 | template <typename... Types> |
| 748 | constexpr variant_internal::RequireAllHaveNotEqualT<Types...> operator!=( |
| 749 | const variant<Types...>& a, const variant<Types...>& b) { |
| 750 | return (a.index() != b.index()) || |
| 751 | variant_internal::VisitIndices<sizeof...(Types)>::Run( |
| 752 | variant_internal::NotEqualsOp<Types...>{&a, &b}, a.index()); |
| 753 | } |
| 754 | |
| 755 | // Less-than operator |
| 756 | template <typename... Types> |
| 757 | constexpr variant_internal::RequireAllHaveLessThanT<Types...> operator<( |
| 758 | const variant<Types...>& a, const variant<Types...>& b) { |
| 759 | return (a.index() != b.index()) |
| 760 | ? (a.index() + 1) < (b.index() + 1) |
| 761 | : variant_internal::VisitIndices<sizeof...(Types)>::Run( |
| 762 | variant_internal::LessThanOp<Types...>{&a, &b}, a.index()); |
| 763 | } |
| 764 | |
| 765 | // Greater-than operator |
| 766 | template <typename... Types> |
| 767 | constexpr variant_internal::RequireAllHaveGreaterThanT<Types...> operator>( |
| 768 | const variant<Types...>& a, const variant<Types...>& b) { |
| 769 | return (a.index() != b.index()) |
| 770 | ? (a.index() + 1) > (b.index() + 1) |
| 771 | : variant_internal::VisitIndices<sizeof...(Types)>::Run( |
| 772 | variant_internal::GreaterThanOp<Types...>{&a, &b}, |
| 773 | a.index()); |
| 774 | } |
| 775 | |
| 776 | // Less-than or equal-to operator |
| 777 | template <typename... Types> |
| 778 | constexpr variant_internal::RequireAllHaveLessThanOrEqualT<Types...> operator<=( |
| 779 | const variant<Types...>& a, const variant<Types...>& b) { |
| 780 | return (a.index() != b.index()) |
| 781 | ? (a.index() + 1) < (b.index() + 1) |
| 782 | : variant_internal::VisitIndices<sizeof...(Types)>::Run( |
| 783 | variant_internal::LessThanOrEqualsOp<Types...>{&a, &b}, |
| 784 | a.index()); |
| 785 | } |
| 786 | |
| 787 | // Greater-than or equal-to operator |
| 788 | template <typename... Types> |
| 789 | constexpr variant_internal::RequireAllHaveGreaterThanOrEqualT<Types...> |
| 790 | operator>=(const variant<Types...>& a, const variant<Types...>& b) { |
| 791 | return (a.index() != b.index()) |
| 792 | ? (a.index() + 1) > (b.index() + 1) |
| 793 | : variant_internal::VisitIndices<sizeof...(Types)>::Run( |
| 794 | variant_internal::GreaterThanOrEqualsOp<Types...>{&a, &b}, |
| 795 | a.index()); |
| 796 | } |
| 797 | |
| 798 | } // namespace absl |
| 799 | |
| 800 | namespace std { |
| 801 | |
| 802 | // hash() |
| 803 | template <> // NOLINT |
| 804 | struct hash<absl::monostate> { |
| 805 | std::size_t operator()(absl::monostate) const { return 0; } |
| 806 | }; |
| 807 | |
| 808 | template <class... T> // NOLINT |
| 809 | struct hash<absl::variant<T...>> |
| 810 | : absl::variant_internal::VariantHashBase<absl::variant<T...>, void, |
| 811 | absl::remove_const_t<T>...> {}; |
| 812 | |
| 813 | } // namespace std |
| 814 | |
| 815 | #endif // ABSL_HAVE_STD_VARIANT |
| 816 | |
| 817 | namespace absl { |
| 818 | namespace variant_internal { |
| 819 | |
| 820 | // Helper visitor for converting a variant<Ts...>` into another type (mostly |
| 821 | // variant) that can be constructed from any type. |
| 822 | template <typename To> |
| 823 | struct ConversionVisitor { |
| 824 | template <typename T> |
| 825 | To operator()(T&& v) const { |
| 826 | return To(std::forward<T>(v)); |
| 827 | } |
| 828 | }; |
| 829 | |
| 830 | } // namespace variant_internal |
| 831 | |
| 832 | // ConvertVariantTo() |
| 833 | // |
| 834 | // Helper functions to convert an `absl::variant` to a variant of another set of |
| 835 | // types, provided that the alternative type of the new variant type can be |
| 836 | // converted from any type in the source variant. |
| 837 | // |
| 838 | // Example: |
| 839 | // |
| 840 | // absl::variant<name1, name2, float> InternalReq(const Req&); |
| 841 | // |
| 842 | // // name1 and name2 are convertible to name |
| 843 | // absl::variant<name, float> ExternalReq(const Req& req) { |
| 844 | // return absl::ConvertVariantTo<absl::variant<name, float>>( |
| 845 | // InternalReq(req)); |
| 846 | // } |
| 847 | template <typename To, typename Variant> |
| 848 | To ConvertVariantTo(Variant&& variant) { |
| 849 | return absl::visit(variant_internal::ConversionVisitor<To>{}, |
| 850 | std::forward<Variant>(variant)); |
| 851 | } |
| 852 | |
| 853 | } // namespace absl |
| 854 | |
| 855 | #endif // ABSL_TYPES_VARIANT_H_ |
| 856 | |