• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TYPES_VARIANT_UTIL_H_
6 #define BASE_TYPES_VARIANT_UTIL_H_
7 
8 #include <stddef.h>
9 
10 #include <type_traits>
11 
12 #include "base/types/always_false.h"
13 #include "third_party/abseil-cpp/absl/types/variant.h"
14 
15 namespace base {
16 namespace internal {
17 
18 template <typename Variant, typename T>
19 struct VariantIndexOfTypeHelper {
20   static_assert(AlwaysFalse<Variant>, "Variant must be an absl::variant<...>");
21 };
22 
23 template <typename... Ts, typename T>
24 struct VariantIndexOfTypeHelper<absl::variant<Ts...>, T> {
25   static constexpr size_t Index() {
26     static_assert(std::is_constructible_v<absl::variant<LiteralType<Ts>...>,
27                                           LiteralType<T>>,
28                   "Variant is not constructible from T");
29     return absl::variant<LiteralType<Ts>...>(LiteralType<T>()).index();
30   }
31 
32   // Helper struct; even if `Tag` may not be usable as a literal type, a
33   // `LiteralType<Tag>` will be.
34   template <typename Tag>
35   struct LiteralType {};
36 };
37 
38 }  // namespace internal
39 
40 // Returns the 0-based index of `T` in `Variant`'s list of alternative types,
41 // e.g. given `Variant` == `absl::variant<A, B, C>` and `T` == `B`, returns 1.
42 //
43 // Note that this helper cannot be used if the list of alternative types
44 // contains duplicates.
45 template <typename Variant, typename T>
46 constexpr size_t VariantIndexOfType() {
47   return internal::VariantIndexOfTypeHelper<Variant, T>::Index();
48 }
49 
50 }  // namespace base
51 
52 #endif  // BASE_TYPES_VARIANT_UTIL_H_
53