1 #pragma once 2 #include <type_traits> 3 #include <variant> 4 5 /** See `sdbusplus::utility::dedup_variant` below. */ 6 7 namespace sdbusplus 8 { 9 namespace utility 10 { 11 12 namespace details 13 { 14 15 /** Find the deduplicated variant type. 16 * 17 * @tparam T - A type of the form 'variant<...>'. 18 * @tparam Unused - An empty type set (non-empty sets are matched in 19 * specialization). 20 * 21 * This template is only matched when Unused is empty, which means all 22 * types have been processed (deduplicated). 23 */ 24 template <typename T, typename... Unused> 25 struct dedup_variant 26 { 27 using type = T; 28 static_assert(sizeof...(Unused) == 0); 29 }; 30 31 /** Find the deduplicated variant type. 32 * 33 * @tparam Done - The types which have already been deduplicated. 34 * @tparam First - The first type to be deduplicated. 35 * @tparam Rest - The remaining types to be deduplicated. 36 * 37 * This template specialization is matched when there are remaining 38 * items to be analyzed, since the 'First' is a stronger match than the 39 * (empty) 'Types' in the previous template. 40 * 41 * Check for First in Done and recursively create the variant type as 42 * appropriate (add First if First not in Done, skip otherwise). 43 */ 44 template <typename... Done, typename First, typename... Rest> 45 struct dedup_variant<std::variant<Done...>, First, Rest...> : 46 public std::conditional_t< 47 (std::is_same_v<First, Done> || ...), 48 dedup_variant<std::variant<Done...>, Rest...>, 49 dedup_variant<std::variant<Done..., First>, Rest...>> 50 {}; 51 52 } // namespace details 53 54 /** This type is useful for generated code which may inadvertently contain 55 * duplicate types if specified simply as `std::variant<A, B, C>`. Some 56 * types, such as `uint32_t` and `size_t` are the same on some architectures 57 * and different on others. `dedup_variant_t<uint32_t, size_t>` will evaluate 58 * to `std::variant<uint32_t>` on architectures where there is a collision. 59 */ 60 template <typename T, typename... Types> 61 using dedup_variant_t = 62 typename details::dedup_variant<std::variant<T>, Types...>::type; 63 64 // Keep temporarily for backwards compatibility. 65 // openbmc/bmcweb 66 // openbmc/smbios-mdr 67 template <typename T, typename... Types> 68 using dedup_variant = dedup_variant_t<T, Types...>; 69 70 } // namespace utility 71 } // namespace sdbusplus 72