1 //===- DenseMapInfoVariant.h - Type traits for DenseMap<variant> *- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file defines DenseMapInfo traits for DenseMap<std::variant<Ts...>>. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_ADT_DENSEMAPINFOVARIANT_H 15 #define LLVM_ADT_DENSEMAPINFOVARIANT_H 16 17 #include "llvm/ADT/DenseMapInfo.h" 18 #include <utility> 19 #include <variant> 20 21 namespace llvm { 22 23 // Provide DenseMapInfo for variants whose all alternatives have DenseMapInfo. 24 template <typename... Ts> struct DenseMapInfo<std::variant<Ts...>> { 25 using Variant = std::variant<Ts...>; 26 using FirstT = std::variant_alternative_t<0, Variant>; 27 28 static inline Variant getEmptyKey() { 29 return Variant(std::in_place_index<0>, DenseMapInfo<FirstT>::getEmptyKey()); 30 } 31 32 static inline Variant getTombstoneKey() { 33 return Variant(std::in_place_index<0>, 34 DenseMapInfo<FirstT>::getTombstoneKey()); 35 } 36 37 static unsigned getHashValue(const Variant &Val) { 38 return std::visit( 39 [&Val](auto &&Alternative) { 40 using T = std::decay_t<decltype(Alternative)>; 41 // Include index in hash to make sure same value as different 42 // alternatives don't collide. 43 return DenseMapInfo<std::pair<size_t, T>>::getHashValuePiecewise( 44 Val.index(), Alternative); 45 }, 46 Val); 47 } 48 49 static bool isEqual(const Variant &LHS, const Variant &RHS) { 50 if (LHS.index() != RHS.index()) 51 return false; 52 if (LHS.valueless_by_exception()) 53 return true; 54 // We want to dispatch to DenseMapInfo<T>::isEqual(LHS.get(I), RHS.get(I)) 55 // We know the types are the same, but std::visit(V, LHS, RHS) doesn't. 56 // We erase the type held in LHS to void*, and dispatch over RHS. 57 const void *ErasedLHS = 58 std::visit([](const auto &LHS) -> const void * { return &LHS; }, LHS); 59 return std::visit( 60 [&](const auto &RHS) -> bool { 61 using T = std::remove_cv_t<std::remove_reference_t<decltype(RHS)>>; 62 return DenseMapInfo<T>::isEqual(*static_cast<const T *>(ErasedLHS), 63 RHS); 64 }, 65 RHS); 66 } 67 }; 68 69 } // end namespace llvm 70 71 #endif // LLVM_ADT_DENSEMAPINFOVARIANT_H 72