1 #pragma once
2 #include <sdbusplus/utility/dedup_variant.hpp>
3 
4 #include <variant>
5 
6 /** See `sdbusplus::utility::merge_variants` below. */
7 
8 namespace sdbusplus
9 {
10 namespace utility
11 {
12 
13 namespace details
14 {
15 
16 /** Find the deduplicated variant type.
17  *
18  *  @tparam T - A type of the form 'variant<...>'.
19  *  @tparam Unused - An empty type set (non-empty sets are matched in
20  *                   specialization).
21  *
22  *  This template is only matched when Unused is empty, which means all
23  *  types have been processed (merged).
24  */
25 template <typename T, typename... Unused>
26 struct merge_variants
27 {
28     using type = T;
29     static_assert(sizeof...(Unused) == 0);
30 };
31 
32 /** Compute the merged variant type.
33  *
34  * @tparam D - Done - Head and tail of the alternative types list of the
35  * first variant.
36  * @tparam Next - The types of the next variant<...> to be merged with the
37  * first.
38  * @tparam Rest - The remaining variants to be merged.
39  *
40  * Use dedup_variant_t to recursively combine alternative types of all the
41  * supplied variants without duplication.
42  */
43 template <typename D, typename... Done, typename... Next, typename... Rest>
44 struct merge_variants<std::variant<D, Done...>, std::variant<Next...>,
45                       Rest...> :
46     public merge_variants<
47         sdbusplus::utility::dedup_variant_t<D, Done..., Next...>, Rest...>
48 {};
49 
50 } // namespace details
51 
52 /** This type is useful for processing D-Bus messages containing information for
53  * multiple interfaces. For doing sdbusplus::message::message::read() on them
54  * one needs to define an std::variant which would be a combination of all the
55  * PropertiesVariant's involved. */
56 template <typename... T>
57 using merge_variants_t = typename details::merge_variants<T...>::type;
58 
59 } // namespace utility
60 } // namespace sdbusplus
61