Search code examples
c++tuplesc++14metaprogramming

Common types in two TypeSets / Tuples


I have two tuples -- TypeSets modeled as tuples, and thus guaranteed to contain each type at maximum once in their parameter packs, to be exact -- (say A = std::tuple<T1, T2> and B = std::tuple<T2, T3>), and I wish to obtain a typedef that corresponds to a tuple of types in the intersection of A and B (in this case, tuple_intersect<A,B>::type = std::tuple<T2>). How do I go about this?


Solution

  • You can use the indices trick along with has_type (from here):

    #include <tuple>
    #include <type_traits>
    
    // ##############################################
    // from https://stackoverflow.com/a/25958302/678093
    template <typename T, typename Tuple>
    struct has_type;
    
    template <typename T>
    struct has_type<T, std::tuple<>> : std::false_type {};
    
    template <typename T, typename U, typename... Ts>
    struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};
    
    template <typename T, typename... Ts>
    struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};
    // ##############################################
    
    
    template <typename S1, typename S2>
    struct intersect
    {
    template <std::size_t... Indices>
    static constexpr auto make_intersection(std::index_sequence<Indices...> ) {
    
        return std::tuple_cat(
            std::conditional_t<
                has_type<
                    std::tuple_element_t<Indices, S1>,
                    S2
                    >::value,
                    std::tuple<std::tuple_element_t<Indices, S1>>,
                    std::tuple<>
    
        >{}...);
    }
    using type = decltype(make_intersection(std::make_index_sequence<std::tuple_size<S1>::value>{}));
    };
    
    
    struct T1{};
    struct T2{};
    struct T3{};
    using A = std::tuple<T1, T2>;
    using B = std::tuple<T2, T3>;
    
    int main()
    {
       static_assert(std::is_same<std::tuple<T2>, intersect<A, B>::type>::value, "");
    }
    

    live example