-- cd076f55c1fa600131f6dda392533dfe61679fc0 by Abseil Team <absl-team@google.com>: Internal change PiperOrigin-RevId: 224008762 -- e05f62b01286d51044ff86ec6ef565749b9faf82 by Abseil Team <absl-team@google.com>: Create a pow10() test helper function to compute guaranteed-precise double values of 10^x. Not all standard libraries ship bit-accurate pow() functions, causing tests to fail that rely on expected values generated by it. PiperOrigin-RevId: 223883762 -- fd88e5e3f7ab80f7f5df9fd1488cd58b4573be69 by Abseil Team <absl-team@google.com>: Remove some absl:: qualifications to work around inline namespace bugs on MSVC 2015. PiperOrigin-RevId: 223869642 -- 6276cfff969d596edd36a2bbaba65ee045808903 by Abseil Team <absl-team@google.com>: Update absl/memory/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 223854224 -- 359de9afc7a34c975fd3e0cbc52afd96637d97bd by Chris Kennelly <ckennelly@google.com>: Mark spinlock_benchmark_common as alwayslink = 1. PiperOrigin-RevId: 223844536 -- 450cd8cbe2789a6d54ed1eb87170259bb334f8b9 by Abseil Team <absl-team@google.com>: Support .* (pointer-to-member dereference) expressions in demangle.cc. PiperOrigin-RevId: 223826797 -- 772ca92179c3634f3e31a80bbc272ed8022e3572 by Abseil Team <absl-team@google.com>: Fix misspellings in absl::variant comments and replace a ' with a `. PiperOrigin-RevId: 223807911 -- 35dcdc2fbf299d195658aac101887f6dcad1de2f by Abseil Team <absl-team@google.com>: Bug fix in CMakeLists.txt file (SRCS --> HDRS). The compressed_tuple header-only library is being defined with the SRCS parameter instead of the HDRS parameter and this has been observed to cause some builds on some platforms to attempt to create a static library from it which fails since there are no .cc sources. PiperOrigin-RevId: 223805367 -- 4a57a3d2045bb137c0c97958e45ce425190b8d3e by Chris Kennelly <ckennelly@google.com>: Add test that absl::make_unique value initializes memory. PiperOrigin-RevId: 223801819 -- dfe8289d7f4dcc6bb568a26aaf192a89e896bdfd by Chris Kennelly <ckennelly@google.com>: SpinLock: Use exchange to avoid missing wakeups. The default fast path for SpinLock::Unlock does not use an atomic. If the SpinLock becomes contended while we are unlocking between lockword_.load and lockword_.store, we will fail to wake up the new waiter. This can cause unexpected latency spikes. PiperOrigin-RevId: 223800369 -- 9b9d35df786482f0016f77dd31691eff81503d23 by Abseil Team <absl-team@google.com>: Update absl/hash/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 223755819 -- c2014e2704b87e7cdce2d2a0287c7e2397752296 by Abseil Team <absl-team@google.com>: Update absl/debugging/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 223751986 -- d83a4e09126400e3fd80645cb03ee558f532271e by Derek Mauro <dmauro@google.com>: Cleanup synchronization benchmarks. PiperOrigin-RevId: 223589416 -- fad140b473586531b5b12843f942ec27dfcf5e93 by CJ Johnson <johnsoncj@google.com>: Makes unifies the order of forward_iterator and input_iterator overloads PiperOrigin-RevId: 223580660 -- 6cd7c96faa7cc5f79f574e35a1b13837ef187d05 by Abseil Team <absl-team@google.com>: Internal Change. PiperOrigin-RevId: 223561629 -- bd2e545356b0f548af0e3c14bb2f7f0e712e49d0 by Shaindel Schwartz <shaindel@google.com>: Remove misleading comments. try_emplace() does not exist for the hash_set containers. PiperOrigin-RevId: 223543089 -- 0cd380a53b587eb7aacc4003a4a3bbb6c78d7c10 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 223512551 -- 7156dfee599cb72e9adddfe0e6ae07a95ddf10bb by Greg Miller <jgm@google.com>: Fixes UB that would result from constructing, multiplying, or dividing a Duration with a double "NaN" value. This CL changes the absl::Duration *implementation* to return an InfiniteDuration value that has the same sign as the given NaN. PiperOrigin-RevId: 223407499 -- 196b7d18609958267951882baf7f9429e49bcafa by CJ Johnson <johnsoncj@google.com>: Addresses NVCC+MSVC compilation bug where `inlined_capacity()` was not considered valid in constexpr PiperOrigin-RevId: 223397718 GitOrigin-RevId: cd076f55c1fa600131f6dda392533dfe61679fc0 Change-Id: I5423ca6470f661a7c6f73aa8fee49990446f157f
		
			
				
	
	
		
			850 lines
		
	
	
	
		
			33 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			850 lines
		
	
	
	
		
			33 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2018 The Abseil Authors.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //      http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| //
 | |
| // -----------------------------------------------------------------------------
 | |
| // variant.h
 | |
| // -----------------------------------------------------------------------------
 | |
| //
 | |
| // This header file defines an `absl::variant` type for holding a type-safe
 | |
| // value of some prescribed set of types (noted as alternative types), and
 | |
| // associated functions for managing variants.
 | |
| //
 | |
| // The `absl::variant` type is a form of type-safe union. An `absl::variant`
 | |
| // should always hold a value of one of its alternative types (except in the
 | |
| // "valueless by exception state" -- see below). A default-constructed
 | |
| // `absl::variant` will hold the value of its first alternative type, provided
 | |
| // it is default-constructable.
 | |
| //
 | |
| // In exceptional cases due to error, an `absl::variant` can hold no
 | |
| // value (known as a "valueless by exception" state), though this is not the
 | |
| // norm.
 | |
| //
 | |
| // As with `absl::optional`, an `absl::variant` -- when it holds a value --
 | |
| // allocates a value of that type directly within the `variant` itself; it
 | |
| // cannot hold a reference, array, or the type `void`; it can, however, hold a
 | |
| // pointer to externally managed memory.
 | |
| //
 | |
| // `absl::variant` is a C++11 compatible version of the C++17 `std::variant`
 | |
| // abstraction and is designed to be a drop-in replacement for code compliant
 | |
| // with C++17.
 | |
| 
 | |
| #ifndef ABSL_TYPES_VARIANT_H_
 | |
| #define ABSL_TYPES_VARIANT_H_
 | |
| 
 | |
| #include "absl/base/config.h"
 | |
| #include "absl/utility/utility.h"
 | |
| 
 | |
| #ifdef ABSL_HAVE_STD_VARIANT
 | |
| 
 | |
| #include <variant>
 | |
| 
 | |
| namespace absl {
 | |
| using std::bad_variant_access;
 | |
| using std::get;
 | |
| using std::get_if;
 | |
| using std::holds_alternative;
 | |
| using std::monostate;
 | |
| using std::variant;
 | |
| using std::variant_alternative;
 | |
| using std::variant_alternative_t;
 | |
| using std::variant_npos;
 | |
| using std::variant_size;
 | |
| using std::variant_size_v;
 | |
| using std::visit;
 | |
| }  // namespace absl
 | |
| 
 | |
| #else  // ABSL_HAVE_STD_VARIANT
 | |
| 
 | |
| #include <functional>
 | |
| #include <new>
 | |
| #include <type_traits>
 | |
| #include <utility>
 | |
| 
 | |
| #include "absl/base/macros.h"
 | |
| #include "absl/base/port.h"
 | |
| #include "absl/meta/type_traits.h"
 | |
| #include "absl/types/internal/variant.h"
 | |
| 
 | |
| namespace absl {
 | |
| 
 | |
| // -----------------------------------------------------------------------------
 | |
| // absl::variant
 | |
| // -----------------------------------------------------------------------------
 | |
| //
 | |
| // An `absl::variant` type is a form of type-safe union. An `absl::variant` --
 | |
| // except in exceptional cases -- always holds a value of one of its alternative
 | |
| // types.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //   // Construct a variant that holds either an integer or a std::string and
 | |
| //   // assign it to a std::string.
 | |
| //   absl::variant<int, std::string> v = std::string("abc");
 | |
| //
 | |
| //   // A default-contructed variant will hold a value-initialized value of
 | |
| //   // the first alternative type.
 | |
| //   auto a = absl::variant<int, std::string>();   // Holds an int of value '0'.
 | |
| //
 | |
| //   // variants are assignable.
 | |
| //
 | |
| //   // copy assignment
 | |
| //   auto v1 = absl::variant<int, std::string>("abc");
 | |
| //   auto v2 = absl::variant<int, std::string>(10);
 | |
| //   v2 = v1;  // copy assign
 | |
| //
 | |
| //   // move assignment
 | |
| //   auto v1 = absl::variant<int, std::string>("abc");
 | |
| //   v1 = absl::variant<int, std::string>(10);
 | |
| //
 | |
| //   // assignment through type conversion
 | |
| //   a = 128;         // variant contains int
 | |
| //   a = "128";       // variant contains std::string
 | |
| //
 | |
| // An `absl::variant` holding a value of one of its alternative types `T` holds
 | |
| // an allocation of `T` directly within the variant itself. An `absl::variant`
 | |
| // is not allowed to allocate additional storage, such as dynamic memory, to
 | |
| // allocate the contained value. The contained value shall be allocated in a
 | |
| // region of the variant storage suitably aligned for all alternative types.
 | |
| template <typename... Ts>
 | |
| class variant;
 | |
| 
 | |
| // swap()
 | |
| //
 | |
| // Swaps two `absl::variant` values. This function is equivalent to `v.swap(w)`
 | |
| // where `v` and `w` are `absl::variant` types.
 | |
| //
 | |
| // Note that this function requires all alternative types to be both swappable
 | |
| // and move-constructible, because any two variants may refer to either the same
 | |
| // type (in which case, they will be swapped) or to two different types (in
 | |
| // which case the values will need to be moved).
 | |
| //
 | |
| template <typename... Ts>
 | |
| void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
 | |
|   v.swap(w);
 | |
| }
 | |
| 
 | |
| // variant_size
 | |
| //
 | |
| // Returns the number of alternative types available for a given `absl::variant`
 | |
| // type as a compile-time constant expression. As this is a class template, it
 | |
| // is not generally useful for accessing the number of alternative types of
 | |
| // any given `absl::variant` instance.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //   auto a = absl::variant<int, std::string>;
 | |
| //   constexpr int num_types =
 | |
| //       absl::variant_size<absl::variant<int, std::string>>();
 | |
| //
 | |
| //   // You can also use the member constant `value`.
 | |
| //   constexpr int num_types =
 | |
| //       absl::variant_size<absl::variant<int, std::string>>::value;
 | |
| //
 | |
| //   // `absl::variant_size` is more valuable for use in generic code:
 | |
| //   template <typename Variant>
 | |
| //   constexpr bool IsVariantMultivalue() {
 | |
| //       return absl::variant_size<Variant>() > 1;
 | |
| //   }
 | |
| //
 | |
| // Note that the set of cv-qualified specializations of `variant_size` are
 | |
| // provided to ensure that those specializations compile (especially when passed
 | |
| // within template logic).
 | |
| template <class T>
 | |
| struct variant_size;
 | |
| 
 | |
| template <class... Ts>
 | |
| struct variant_size<variant<Ts...>>
 | |
|     : std::integral_constant<std::size_t, sizeof...(Ts)> {};
 | |
| 
 | |
| // Specialization of `variant_size` for const qualified variants.
 | |
| template <class T>
 | |
| struct variant_size<const T> : variant_size<T>::type {};
 | |
| 
 | |
| // Specialization of `variant_size` for volatile qualified variants.
 | |
| template <class T>
 | |
| struct variant_size<volatile T> : variant_size<T>::type {};
 | |
| 
 | |
| // Specialization of `variant_size` for const volatile qualified variants.
 | |
| template <class T>
 | |
| struct variant_size<const volatile T> : variant_size<T>::type {};
 | |
| 
 | |
| // variant_alternative
 | |
| //
 | |
| // Returns the alternative type for a given `absl::variant` at the passed
 | |
| // index value as a compile-time constant expression. As this is a class
 | |
| // template resulting in a type, it is not useful for access of the run-time
 | |
| // value of any given `absl::variant` variable.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //   // The type of the 0th alternative is "int".
 | |
| //   using alternative_type_0
 | |
| //     = absl::variant_alternative<0, absl::variant<int, std::string>>::type;
 | |
| //
 | |
| //   static_assert(std::is_same<alternative_type_0, int>::value, "");
 | |
| //
 | |
| //   // `absl::variant_alternative` is more valuable for use in generic code:
 | |
| //   template <typename Variant>
 | |
| //   constexpr bool IsFirstElementTrivial() {
 | |
| //       return std::is_trivial_v<variant_alternative<0, Variant>::type>;
 | |
| //   }
 | |
| //
 | |
| // Note that the set of cv-qualified specializations of `variant_alternative`
 | |
| // are provided to ensure that those specializations compile (especially when
 | |
| // passed within template logic).
 | |
| template <std::size_t I, class T>
 | |
| struct variant_alternative;
 | |
| 
 | |
| template <std::size_t I, class... Types>
 | |
| struct variant_alternative<I, variant<Types...>> {
 | |
|   using type =
 | |
|       variant_internal::VariantAlternativeSfinaeT<I, variant<Types...>>;
 | |
| };
 | |
| 
 | |
| // Specialization of `variant_alternative` for const qualified variants.
 | |
| template <std::size_t I, class T>
 | |
| struct variant_alternative<I, const T> {
 | |
|   using type = const typename variant_alternative<I, T>::type;
 | |
| };
 | |
| 
 | |
| // Specialization of `variant_alternative` for volatile qualified variants.
 | |
| template <std::size_t I, class T>
 | |
| struct variant_alternative<I, volatile T> {
 | |
|   using type = volatile typename variant_alternative<I, T>::type;
 | |
| };
 | |
| 
 | |
| // Specialization of `variant_alternative` for const volatile qualified
 | |
| // variants.
 | |
| template <std::size_t I, class T>
 | |
| struct variant_alternative<I, const volatile T> {
 | |
|   using type = const volatile typename variant_alternative<I, T>::type;
 | |
| };
 | |
| 
 | |
| // Template type alias for variant_alternative<I, T>::type.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //   using alternative_type_0
 | |
| //     = absl::variant_alternative_t<0, absl::variant<int, std::string>>;
 | |
| //   static_assert(std::is_same<alternative_type_0, int>::value, "");
 | |
| template <std::size_t I, class T>
 | |
| using variant_alternative_t = typename variant_alternative<I, T>::type;
 | |
| 
 | |
| // holds_alternative()
 | |
| //
 | |
| // Checks whether the given variant currently holds a given alternative type,
 | |
| // returning `true` if so.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //   absl::variant<int, std::string> foo = 42;
 | |
| //   if (absl::holds_alternative<int>(foo)) {
 | |
| //       std::cout << "The variant holds an integer";
 | |
| //   }
 | |
| template <class T, class... Types>
 | |
| constexpr bool holds_alternative(const variant<Types...>& v) noexcept {
 | |
|   static_assert(
 | |
|       variant_internal::UnambiguousIndexOfImpl<variant<Types...>, T,
 | |
|                                                0>::value != sizeof...(Types),
 | |
|       "The type T must occur exactly once in Types...");
 | |
|   return v.index() ==
 | |
|          variant_internal::UnambiguousIndexOf<variant<Types...>, T>::value;
 | |
| }
 | |
| 
 | |
| // get()
 | |
| //
 | |
| // Returns a reference to the value currently within a given variant, using
 | |
| // either a unique alternative type amongst the variant's set of alternative
 | |
| // types, or the variant's index value. Attempting to get a variant's value
 | |
| // using a type that is not unique within the variant's set of alternative types
 | |
| // is a compile-time error. If the index of the alternative being specified is
 | |
| // different from the index of the alternative that is currently stored, throws
 | |
| // `absl::bad_variant_access`.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //   auto a = absl::variant<int, std::string>;
 | |
| //
 | |
| //   // Get the value by type (if unique).
 | |
| //   int i = absl::get<int>(a);
 | |
| //
 | |
| //   auto b = absl::variant<int, int>;
 | |
| //
 | |
| //   // Getting the value by a type that is not unique is ill-formed.
 | |
| //   int j = absl::get<int>(b);     // Compile Error!
 | |
| //
 | |
| //   // Getting value by index not ambiguous and allowed.
 | |
| //   int k = absl::get<1>(b);
 | |
| 
 | |
| // Overload for getting a variant's lvalue by type.
 | |
| template <class T, class... Types>
 | |
| constexpr T& get(variant<Types...>& v) {  // NOLINT
 | |
|   return variant_internal::VariantCoreAccess::CheckedAccess<
 | |
|       variant_internal::IndexOf<T, Types...>::value>(v);
 | |
| }
 | |
| 
 | |
| // Overload for getting a variant's rvalue by type.
 | |
| // Note: `absl::move()` is required to allow use of constexpr in C++11.
 | |
| template <class T, class... Types>
 | |
| constexpr T&& get(variant<Types...>&& v) {
 | |
|   return variant_internal::VariantCoreAccess::CheckedAccess<
 | |
|       variant_internal::IndexOf<T, Types...>::value>(absl::move(v));
 | |
| }
 | |
| 
 | |
| // Overload for getting a variant's const lvalue by type.
 | |
| template <class T, class... Types>
 | |
| constexpr const T& get(const variant<Types...>& v) {
 | |
|   return variant_internal::VariantCoreAccess::CheckedAccess<
 | |
|       variant_internal::IndexOf<T, Types...>::value>(v);
 | |
| }
 | |
| 
 | |
| // Overload for getting a variant's const rvalue by type.
 | |
| // Note: `absl::move()` is required to allow use of constexpr in C++11.
 | |
| template <class T, class... Types>
 | |
| constexpr const T&& get(const variant<Types...>&& v) {
 | |
|   return variant_internal::VariantCoreAccess::CheckedAccess<
 | |
|       variant_internal::IndexOf<T, Types...>::value>(absl::move(v));
 | |
| }
 | |
| 
 | |
| // Overload for getting a variant's lvalue by index.
 | |
| template <std::size_t I, class... Types>
 | |
| constexpr variant_alternative_t<I, variant<Types...>>& get(
 | |
|     variant<Types...>& v) {  // NOLINT
 | |
|   return variant_internal::VariantCoreAccess::CheckedAccess<I>(v);
 | |
| }
 | |
| 
 | |
| // Overload for getting a variant's rvalue by index.
 | |
| // Note: `absl::move()` is required to allow use of constexpr in C++11.
 | |
| template <std::size_t I, class... Types>
 | |
| constexpr variant_alternative_t<I, variant<Types...>>&& get(
 | |
|     variant<Types...>&& v) {
 | |
|   return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v));
 | |
| }
 | |
| 
 | |
| // Overload for getting a variant's const lvalue by index.
 | |
| template <std::size_t I, class... Types>
 | |
| constexpr const variant_alternative_t<I, variant<Types...>>& get(
 | |
|     const variant<Types...>& v) {
 | |
|   return variant_internal::VariantCoreAccess::CheckedAccess<I>(v);
 | |
| }
 | |
| 
 | |
| // Overload for getting a variant's const rvalue by index.
 | |
| // Note: `absl::move()` is required to allow use of constexpr in C++11.
 | |
| template <std::size_t I, class... Types>
 | |
| constexpr const variant_alternative_t<I, variant<Types...>>&& get(
 | |
|     const variant<Types...>&& v) {
 | |
|   return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v));
 | |
| }
 | |
| 
 | |
| // get_if()
 | |
| //
 | |
| // Returns a pointer to the value currently stored within a given variant, if
 | |
| // present, using either a unique alternative type amongst the variant's set of
 | |
| // alternative types, or the variant's index value. If such a value does not
 | |
| // exist, returns `nullptr`.
 | |
| //
 | |
| // As with `get`, attempting to get a variant's value using a type that is not
 | |
| // unique within the variant's set of alternative types is a compile-time error.
 | |
| 
 | |
| // Overload for getting a pointer to the value stored in the given variant by
 | |
| // index.
 | |
| template <std::size_t I, class... Types>
 | |
| constexpr absl::add_pointer_t<variant_alternative_t<I, variant<Types...>>>
 | |
| get_if(variant<Types...>* v) noexcept {
 | |
|   return (v != nullptr && v->index() == I)
 | |
|              ? std::addressof(
 | |
|                    variant_internal::VariantCoreAccess::Access<I>(*v))
 | |
|              : nullptr;
 | |
| }
 | |
| 
 | |
| // Overload for getting a pointer to the const value stored in the given
 | |
| // variant by index.
 | |
| template <std::size_t I, class... Types>
 | |
| constexpr absl::add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
 | |
| get_if(const variant<Types...>* v) noexcept {
 | |
|   return (v != nullptr && v->index() == I)
 | |
|              ? std::addressof(
 | |
|                    variant_internal::VariantCoreAccess::Access<I>(*v))
 | |
|              : nullptr;
 | |
| }
 | |
| 
 | |
| // Overload for getting a pointer to the value stored in the given variant by
 | |
| // type.
 | |
| template <class T, class... Types>
 | |
| constexpr absl::add_pointer_t<T> get_if(variant<Types...>* v) noexcept {
 | |
|   return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
 | |
| }
 | |
| 
 | |
| // Overload for getting a pointer to the const value stored in the given variant
 | |
| // by type.
 | |
| template <class T, class... Types>
 | |
| constexpr absl::add_pointer_t<const T> get_if(
 | |
|     const variant<Types...>* v) noexcept {
 | |
|   return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
 | |
| }
 | |
| 
 | |
| // visit()
 | |
| //
 | |
| // Calls a provided functor on a given set of variants. `absl::visit()` is
 | |
| // commonly used to conditionally inspect the state of a given variant (or set
 | |
| // of variants).
 | |
| //
 | |
| // The functor must return the same type when called with any of the variants'
 | |
| // alternatives.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //   // Define a visitor functor
 | |
| //   struct GetVariant {
 | |
| //       template<typename T>
 | |
| //       void operator()(const T& i) const {
 | |
| //         std::cout << "The variant's value is: " << i;
 | |
| //       }
 | |
| //   };
 | |
| //
 | |
| //   // Declare our variant, and call `absl::visit()` on it.
 | |
| //   // Note that `GetVariant()` returns void in either case.
 | |
| //   absl::variant<int, std::string> foo = std::string("foo");
 | |
| //   GetVariant visitor;
 | |
| //   absl::visit(visitor, foo);  // Prints `The variant's value is: foo'
 | |
| template <typename Visitor, typename... Variants>
 | |
| variant_internal::VisitResult<Visitor, Variants...> visit(Visitor&& vis,
 | |
|                                                           Variants&&... vars) {
 | |
|   return variant_internal::
 | |
|       VisitIndices<variant_size<absl::decay_t<Variants> >::value...>::Run(
 | |
|           variant_internal::PerformVisitation<Visitor, Variants...>{
 | |
|               std::forward_as_tuple(absl::forward<Variants>(vars)...),
 | |
|               absl::forward<Visitor>(vis)},
 | |
|           vars.index()...);
 | |
| }
 | |
| 
 | |
| // monostate
 | |
| //
 | |
| // The monostate class serves as a first alternative type for a variant for
 | |
| // which the first variant type is otherwise not default-constructible.
 | |
| struct monostate {};
 | |
| 
 | |
| // `absl::monostate` Relational Operators
 | |
| 
 | |
| constexpr bool operator<(monostate, monostate) noexcept { return false; }
 | |
| constexpr bool operator>(monostate, monostate) noexcept { return false; }
 | |
| constexpr bool operator<=(monostate, monostate) noexcept { return true; }
 | |
| constexpr bool operator>=(monostate, monostate) noexcept { return true; }
 | |
| constexpr bool operator==(monostate, monostate) noexcept { return true; }
 | |
| constexpr bool operator!=(monostate, monostate) noexcept { return false; }
 | |
| 
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // `absl::variant` Template Definition
 | |
| //------------------------------------------------------------------------------
 | |
| template <typename T0, typename... Tn>
 | |
| class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
 | |
|   static_assert(absl::conjunction<std::is_object<T0>,
 | |
|                                   std::is_object<Tn>...>::value,
 | |
|                 "Attempted to instantiate a variant containing a non-object "
 | |
|                 "type.");
 | |
|   // Intentionally not qualifying `negation` with `absl::` to work around a bug
 | |
|   // in MSVC 2015 with inline namespace and variadic template.
 | |
|   static_assert(absl::conjunction<negation<std::is_array<T0> >,
 | |
|                                   negation<std::is_array<Tn> >...>::value,
 | |
|                 "Attempted to instantiate a variant containing an array type.");
 | |
|   static_assert(absl::conjunction<std::is_nothrow_destructible<T0>,
 | |
|                                   std::is_nothrow_destructible<Tn>...>::value,
 | |
|                 "Attempted to instantiate a variant containing a non-nothrow "
 | |
|                 "destructible type.");
 | |
| 
 | |
|   friend struct variant_internal::VariantCoreAccess;
 | |
| 
 | |
|  private:
 | |
|   using Base = variant_internal::VariantBase<T0, Tn...>;
 | |
| 
 | |
|  public:
 | |
|   // Constructors
 | |
| 
 | |
|   // Constructs a variant holding a default-initialized value of the first
 | |
|   // alternative type.
 | |
|   constexpr variant() /*noexcept(see 111above)*/ = default;
 | |
| 
 | |
|   // Copy constructor, standard semantics
 | |
|   variant(const variant& other) = default;
 | |
| 
 | |
|   // Move constructor, standard semantics
 | |
|   variant(variant&& other) /*noexcept(see above)*/ = default;
 | |
| 
 | |
|   // Constructs a variant of an alternative type specified by overload
 | |
|   // resolution of the provided forwarding arguments through
 | |
|   // direct-initialization.
 | |
|   //
 | |
|   // Note: If the selected constructor is a constexpr constructor, this
 | |
|   // constructor shall be a constexpr constructor.
 | |
|   //
 | |
|   // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
 | |
|   // has been voted passed the design phase in the C++ standard meeting in Mar
 | |
|   // 2018. It will be implemented and integrated into `absl::variant`.
 | |
|   template <
 | |
|       class T,
 | |
|       std::size_t I = std::enable_if<
 | |
|           variant_internal::IsNeitherSelfNorInPlace<variant,
 | |
|                                                     absl::decay_t<T>>::value,
 | |
|           variant_internal::IndexOfConstructedType<variant, T>>::type::value,
 | |
|       class Tj = absl::variant_alternative_t<I, variant>,
 | |
|       absl::enable_if_t<std::is_constructible<Tj, T>::value>* =
 | |
|           nullptr>
 | |
|   constexpr variant(T&& t) noexcept(std::is_nothrow_constructible<Tj, T>::value)
 | |
|       : Base(variant_internal::EmplaceTag<I>(), absl::forward<T>(t)) {}
 | |
| 
 | |
|   // Constructs a variant of an alternative type from the arguments through
 | |
|   // direct-initialization.
 | |
|   //
 | |
|   // Note: If the selected constructor is a constexpr constructor, this
 | |
|   // constructor shall be a constexpr constructor.
 | |
|   template <class T, class... Args,
 | |
|             typename std::enable_if<std::is_constructible<
 | |
|                 variant_internal::UnambiguousTypeOfT<variant, T>,
 | |
|                 Args...>::value>::type* = nullptr>
 | |
|   constexpr explicit variant(in_place_type_t<T>, Args&&... args)
 | |
|       : Base(variant_internal::EmplaceTag<
 | |
|                  variant_internal::UnambiguousIndexOf<variant, T>::value>(),
 | |
|              absl::forward<Args>(args)...) {}
 | |
| 
 | |
|   // Constructs a variant of an alternative type from an initializer list
 | |
|   // and other arguments through direct-initialization.
 | |
|   //
 | |
|   // Note: If the selected constructor is a constexpr constructor, this
 | |
|   // constructor shall be a constexpr constructor.
 | |
|   template <class T, class U, class... Args,
 | |
|             typename std::enable_if<std::is_constructible<
 | |
|                 variant_internal::UnambiguousTypeOfT<variant, T>,
 | |
|                 std::initializer_list<U>&, Args...>::value>::type* = nullptr>
 | |
|   constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U> il,
 | |
|                              Args&&... args)
 | |
|       : Base(variant_internal::EmplaceTag<
 | |
|                  variant_internal::UnambiguousIndexOf<variant, T>::value>(),
 | |
|              il, absl::forward<Args>(args)...) {}
 | |
| 
 | |
|   // Constructs a variant of an alternative type from a provided index,
 | |
|   // through value-initialization using the provided forwarded arguments.
 | |
|   template <std::size_t I, class... Args,
 | |
|             typename std::enable_if<std::is_constructible<
 | |
|                 variant_internal::VariantAlternativeSfinaeT<I, variant>,
 | |
|                 Args...>::value>::type* = nullptr>
 | |
|   constexpr explicit variant(in_place_index_t<I>, Args&&... args)
 | |
|       : Base(variant_internal::EmplaceTag<I>(), absl::forward<Args>(args)...) {}
 | |
| 
 | |
|   // Constructs a variant of an alternative type from a provided index,
 | |
|   // through value-initialization of an initializer list and the provided
 | |
|   // forwarded arguments.
 | |
|   template <std::size_t I, class U, class... Args,
 | |
|             typename std::enable_if<std::is_constructible<
 | |
|                 variant_internal::VariantAlternativeSfinaeT<I, variant>,
 | |
|                 std::initializer_list<U>&, Args...>::value>::type* = nullptr>
 | |
|   constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U> il,
 | |
|                              Args&&... args)
 | |
|       : Base(variant_internal::EmplaceTag<I>(), il,
 | |
|              absl::forward<Args>(args)...) {}
 | |
| 
 | |
|   // Destructors
 | |
| 
 | |
|   // Destroys the variant's currently contained value, provided that
 | |
|   // `absl::valueless_by_exception()` is false.
 | |
|   ~variant() = default;
 | |
| 
 | |
|   // Assignment Operators
 | |
| 
 | |
|   // Copy assignment operator
 | |
|   variant& operator=(const variant& other) = default;
 | |
| 
 | |
|   // Move assignment operator
 | |
|   variant& operator=(variant&& other) /*noexcept(see above)*/ = default;
 | |
| 
 | |
|   // Converting assignment operator
 | |
|   //
 | |
|   // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
 | |
|   // has been voted passed the design phase in the C++ standard meeting in Mar
 | |
|   // 2018. It will be implemented and integrated into `absl::variant`.
 | |
|   template <
 | |
|       class T,
 | |
|       std::size_t I = std::enable_if<
 | |
|           !std::is_same<absl::decay_t<T>, variant>::value,
 | |
|           variant_internal::IndexOfConstructedType<variant, T>>::type::value,
 | |
|       class Tj = absl::variant_alternative_t<I, variant>,
 | |
|       typename std::enable_if<std::is_assignable<Tj&, T>::value &&
 | |
|                               std::is_constructible<Tj, T>::value>::type* =
 | |
|           nullptr>
 | |
|   variant& operator=(T&& t) noexcept(
 | |
|       std::is_nothrow_assignable<Tj&, T>::value&&
 | |
|           std::is_nothrow_constructible<Tj, T>::value) {
 | |
|     variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
 | |
|         variant_internal::VariantCoreAccess::MakeConversionAssignVisitor(
 | |
|             this, absl::forward<T>(t)),
 | |
|         index());
 | |
| 
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   // emplace() Functions
 | |
| 
 | |
|   // Constructs a value of the given alternative type T within the variant.
 | |
|   //
 | |
|   // Example:
 | |
|   //
 | |
|   //   absl::variant<std::vector<int>, int, std::string> v;
 | |
|   //   v.emplace<int>(99);
 | |
|   //   v.emplace<std::string>("abc");
 | |
|   template <
 | |
|       class T, class... Args,
 | |
|       typename std::enable_if<std::is_constructible<
 | |
|           absl::variant_alternative_t<
 | |
|               variant_internal::UnambiguousIndexOf<variant, T>::value, variant>,
 | |
|           Args...>::value>::type* = nullptr>
 | |
|   T& emplace(Args&&... args) {
 | |
|     return variant_internal::VariantCoreAccess::Replace<
 | |
|         variant_internal::UnambiguousIndexOf<variant, T>::value>(
 | |
|         this, absl::forward<Args>(args)...);
 | |
|   }
 | |
| 
 | |
|   // Constructs a value of the given alternative type T within the variant using
 | |
|   // an initializer list.
 | |
|   //
 | |
|   // Example:
 | |
|   //
 | |
|   //   absl::variant<std::vector<int>, int, std::string> v;
 | |
|   //   v.emplace<std::vector<int>>({0, 1, 2});
 | |
|   template <
 | |
|       class T, class U, class... Args,
 | |
|       typename std::enable_if<std::is_constructible<
 | |
|           absl::variant_alternative_t<
 | |
|               variant_internal::UnambiguousIndexOf<variant, T>::value, variant>,
 | |
|           std::initializer_list<U>&, Args...>::value>::type* = nullptr>
 | |
|   T& emplace(std::initializer_list<U> il, Args&&... args) {
 | |
|     return variant_internal::VariantCoreAccess::Replace<
 | |
|         variant_internal::UnambiguousIndexOf<variant, T>::value>(
 | |
|         this, il, absl::forward<Args>(args)...);
 | |
|   }
 | |
| 
 | |
|   // Destroys the current value of the variant (provided that
 | |
|   // `absl::valueless_by_exception()` is false, and constructs a new value at
 | |
|   // the given index.
 | |
|   //
 | |
|   // Example:
 | |
|   //
 | |
|   //   absl::variant<std::vector<int>, int, int> v;
 | |
|   //   v.emplace<1>(99);
 | |
|   //   v.emplace<2>(98);
 | |
|   //   v.emplace<int>(99);  // Won't compile. 'int' isn't a unique type.
 | |
|   template <std::size_t I, class... Args,
 | |
|             typename std::enable_if<
 | |
|                 std::is_constructible<absl::variant_alternative_t<I, variant>,
 | |
|                                       Args...>::value>::type* = nullptr>
 | |
|   absl::variant_alternative_t<I, variant>& emplace(Args&&... args) {
 | |
|     return variant_internal::VariantCoreAccess::Replace<I>(
 | |
|         this, absl::forward<Args>(args)...);
 | |
|   }
 | |
| 
 | |
|   // Destroys the current value of the variant (provided that
 | |
|   // `absl::valueless_by_exception()` is false, and constructs a new value at
 | |
|   // the given index using an initializer list and the provided arguments.
 | |
|   //
 | |
|   // Example:
 | |
|   //
 | |
|   //   absl::variant<std::vector<int>, int, int> v;
 | |
|   //   v.emplace<0>({0, 1, 2});
 | |
|   template <std::size_t I, class U, class... Args,
 | |
|             typename std::enable_if<std::is_constructible<
 | |
|                 absl::variant_alternative_t<I, variant>,
 | |
|                 std::initializer_list<U>&, Args...>::value>::type* = nullptr>
 | |
|   absl::variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il,
 | |
|                                                    Args&&... args) {
 | |
|     return variant_internal::VariantCoreAccess::Replace<I>(
 | |
|         this, il, absl::forward<Args>(args)...);
 | |
|   }
 | |
| 
 | |
|   // variant::valueless_by_exception()
 | |
|   //
 | |
|   // Returns false if and only if the variant currently holds a valid value.
 | |
|   constexpr bool valueless_by_exception() const noexcept {
 | |
|     return this->index_ == absl::variant_npos;
 | |
|   }
 | |
| 
 | |
|   // variant::index()
 | |
|   //
 | |
|   // Returns the index value of the variant's currently selected alternative
 | |
|   // type.
 | |
|   constexpr std::size_t index() const noexcept { return this->index_; }
 | |
| 
 | |
|   // variant::swap()
 | |
|   //
 | |
|   // Swaps the values of two variant objects.
 | |
|   //
 | |
|   // TODO(calabrese)
 | |
|   //   `variant::swap()` and `swap()` rely on `std::is_(nothrow)_swappable()`
 | |
|   //   which is introduced in C++17. So we assume `is_swappable()` is always
 | |
|   //   true and `is_nothrow_swappable()` is same as `std::is_trivial()`.
 | |
|   void swap(variant& rhs) noexcept(
 | |
|       absl::conjunction<std::is_trivial<T0>, std::is_trivial<Tn>...>::value) {
 | |
|     return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
 | |
|         variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
 | |
|   }
 | |
| };
 | |
| 
 | |
| // We need a valid declaration of variant<> for SFINAE and overload resolution
 | |
| // to work properly above, but we don't need a full declaration since this type
 | |
| // will never be constructed. This declaration, though incomplete, suffices.
 | |
| template <>
 | |
| class variant<>;
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Relational Operators
 | |
| //------------------------------------------------------------------------------
 | |
| //
 | |
| // If neither operand is in the `variant::valueless_by_exception` state:
 | |
| //
 | |
| //   * If the index of both variants is the same, the relational operator
 | |
| //     returns the result of the corresponding relational operator for the
 | |
| //     corresponding alternative type.
 | |
| //   * If the index of both variants is not the same, the relational operator
 | |
| //     returns the result of that operation applied to the value of the left
 | |
| //     operand's index and the value of the right operand's index.
 | |
| //   * If at least one operand is in the valueless_by_exception state:
 | |
| //     - A variant in the valueless_by_exception state is only considered equal
 | |
| //       to another variant in the valueless_by_exception state.
 | |
| //     - If exactly one operand is in the valueless_by_exception state, the
 | |
| //       variant in the valueless_by_exception state is less than the variant
 | |
| //       that is not in the valueless_by_exception state.
 | |
| //
 | |
| // Note: The value 1 is added to each index in the relational comparisons such
 | |
| // that the index corresponding to the valueless_by_exception state wraps around
 | |
| // to 0 (the lowest value for the index type), and the remaining indices stay in
 | |
| // the same relative order.
 | |
| 
 | |
| // Equal-to operator
 | |
| template <typename... Types>
 | |
| constexpr variant_internal::RequireAllHaveEqualT<Types...> operator==(
 | |
|     const variant<Types...>& a, const variant<Types...>& b) {
 | |
|   return (a.index() == b.index()) &&
 | |
|          variant_internal::VisitIndices<sizeof...(Types)>::Run(
 | |
|              variant_internal::EqualsOp<Types...>{&a, &b}, a.index());
 | |
| }
 | |
| 
 | |
| // Not equal operator
 | |
| template <typename... Types>
 | |
| constexpr variant_internal::RequireAllHaveNotEqualT<Types...> operator!=(
 | |
|     const variant<Types...>& a, const variant<Types...>& b) {
 | |
|   return (a.index() != b.index()) ||
 | |
|          variant_internal::VisitIndices<sizeof...(Types)>::Run(
 | |
|              variant_internal::NotEqualsOp<Types...>{&a, &b}, a.index());
 | |
| }
 | |
| 
 | |
| // Less-than operator
 | |
| template <typename... Types>
 | |
| constexpr variant_internal::RequireAllHaveLessThanT<Types...> operator<(
 | |
|     const variant<Types...>& a, const variant<Types...>& b) {
 | |
|   return (a.index() != b.index())
 | |
|              ? (a.index() + 1) < (b.index() + 1)
 | |
|              : variant_internal::VisitIndices<sizeof...(Types)>::Run(
 | |
|                    variant_internal::LessThanOp<Types...>{&a, &b}, a.index());
 | |
| }
 | |
| 
 | |
| // Greater-than operator
 | |
| template <typename... Types>
 | |
| constexpr variant_internal::RequireAllHaveGreaterThanT<Types...> operator>(
 | |
|     const variant<Types...>& a, const variant<Types...>& b) {
 | |
|   return (a.index() != b.index())
 | |
|              ? (a.index() + 1) > (b.index() + 1)
 | |
|              : variant_internal::VisitIndices<sizeof...(Types)>::Run(
 | |
|                    variant_internal::GreaterThanOp<Types...>{&a, &b},
 | |
|                    a.index());
 | |
| }
 | |
| 
 | |
| // Less-than or equal-to operator
 | |
| template <typename... Types>
 | |
| constexpr variant_internal::RequireAllHaveLessThanOrEqualT<Types...> operator<=(
 | |
|     const variant<Types...>& a, const variant<Types...>& b) {
 | |
|   return (a.index() != b.index())
 | |
|              ? (a.index() + 1) < (b.index() + 1)
 | |
|              : variant_internal::VisitIndices<sizeof...(Types)>::Run(
 | |
|                    variant_internal::LessThanOrEqualsOp<Types...>{&a, &b},
 | |
|                    a.index());
 | |
| }
 | |
| 
 | |
| // Greater-than or equal-to operator
 | |
| template <typename... Types>
 | |
| constexpr variant_internal::RequireAllHaveGreaterThanOrEqualT<Types...>
 | |
| operator>=(const variant<Types...>& a, const variant<Types...>& b) {
 | |
|   return (a.index() != b.index())
 | |
|              ? (a.index() + 1) > (b.index() + 1)
 | |
|              : variant_internal::VisitIndices<sizeof...(Types)>::Run(
 | |
|                    variant_internal::GreaterThanOrEqualsOp<Types...>{&a, &b},
 | |
|                    a.index());
 | |
| }
 | |
| 
 | |
| }  // namespace absl
 | |
| 
 | |
| namespace std {
 | |
| 
 | |
| // hash()
 | |
| template <>  // NOLINT
 | |
| struct hash<absl::monostate> {
 | |
|   std::size_t operator()(absl::monostate) const { return 0; }
 | |
| };
 | |
| 
 | |
| template <class... T>  // NOLINT
 | |
| struct hash<absl::variant<T...>>
 | |
|     : absl::variant_internal::VariantHashBase<absl::variant<T...>, void,
 | |
|                                               absl::remove_const_t<T>...> {};
 | |
| 
 | |
| }  // namespace std
 | |
| 
 | |
| #endif  // ABSL_HAVE_STD_VARIANT
 | |
| 
 | |
| namespace absl {
 | |
| namespace variant_internal {
 | |
| 
 | |
| // Helper visitor for converting a variant<Ts...>` into another type (mostly
 | |
| // variant) that can be constructed from any type.
 | |
| template <typename To>
 | |
| struct ConversionVisitor {
 | |
|   template <typename T>
 | |
|   To operator()(T&& v) const {
 | |
|     return To(std::forward<T>(v));
 | |
|   }
 | |
| };
 | |
| 
 | |
| }  // namespace variant_internal
 | |
| 
 | |
| // ConvertVariantTo()
 | |
| //
 | |
| // Helper functions to convert an `absl::variant` to a variant of another set of
 | |
| // types, provided that the alternative type of the new variant type can be
 | |
| // converted from any type in the source variant.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //   absl::variant<name1, name2, float> InternalReq(const Req&);
 | |
| //
 | |
| //   // name1 and name2 are convertible to name
 | |
| //   absl::variant<name, float> ExternalReq(const Req& req) {
 | |
| //     return absl::ConvertVariantTo<absl::variant<name, float>>(
 | |
| //              InternalReq(req));
 | |
| //   }
 | |
| template <typename To, typename Variant>
 | |
| To ConvertVariantTo(Variant&& variant) {
 | |
|   return absl::visit(variant_internal::ConversionVisitor<To>{},
 | |
|                      std::forward<Variant>(variant));
 | |
| }
 | |
| 
 | |
| }  // namespace absl
 | |
| 
 | |
| #endif  // ABSL_TYPES_VARIANT_H_
 |