Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if one set of types is a subset of the other

Tags:

How can one check if one parameter pack (interpreted as a set) is a subset of another one?

So far I only have the frame (using std::tuple), but no functionality.

#include <tuple>
#include <type_traits>

template <typename, typename>
struct is_subset_of : std::false_type
{
};

template <typename ... Types1, typename ... Types2>
struct is_subset_of<std::tuple<Types1...>, std::tuple<Types2...>>
    : std::true_type
{
    // Should only be true_type if Types1 is a subset of Types2
};

int main() {
    using t1 = std::tuple<int, double>;
    using t2 = std::tuple<double, int>;
    using t3 = std::tuple<int, double, char>;

    static_assert(is_subset_of<t1, t1>::value, "err");
    static_assert(is_subset_of<t1, t2>::value, "err");
    static_assert(is_subset_of<t2, t1>::value, "err");
    static_assert(is_subset_of<t2, t3>::value, "err");
    static_assert(!is_subset_of<t3, t2>::value, "err");
}

Every type is not allowed to occur more than once in a set.

It would be nice if the solution works with C++11.

like image 931
Tobias Hermann Avatar asked Mar 03 '17 14:03

Tobias Hermann


People also ask

How do you check a list is subset of another list?

issubset() function. The most used and recommended method to check for a sublist. This function is tailor made to perform the particular task of checking if one list is a subset of another.

Is a set a subset of another set?

A set A is a subset of another set B if all elements of the set A are elements of the set B. In other words, the set A is contained inside the set B. The subset relationship is denoted as A⊂B.

How do you check if one set is a subset of another set?

If all the values of a set, A, are also contained in a larger set, B, then A is a subset of B.


2 Answers

#include <tuple>
#include <type_traits>

template <typename T, typename... Ts>
constexpr bool contains = (std::is_same<T, Ts>{} || ...);

template <typename Subset, typename Set>
constexpr bool is_subset_of = false;

template <typename... Ts, typename... Us>
constexpr bool is_subset_of<std::tuple<Ts...>, std::tuple<Us...>>
           = (contains<Ts, Us...> && ...);

DEMO

like image 158
Piotr Skotnicki Avatar answered Sep 19 '22 08:09

Piotr Skotnicki


If you can use C++17 features, I highly recommend using Piotr Skotnicki's solution!

I had to implement this functionality a while ago. I am just going to copy-paste the code I came up with at that point.

I am not claiming that this is the best or most elegant way to implement this kind of check! I did not bother thinking about the edge cases too much; you may need to adapt the code to fit your requirements.

To clarify: ContainsTypes<Lhs, Rhs> checks if Rhs is a subset of Lhs.


  template <typename Tuple, typename T>
  struct ContainsType;

  template <typename T, typename U, typename... Ts>
  struct ContainsType<std::tuple<T, Ts...>, U>
  {
      static const bool VALUE = ContainsType<std::tuple<Ts...>, U>::VALUE;
  };

  template <typename T, typename... Ts>
  struct ContainsType<std::tuple<T, Ts...>, T>
  {
      static const bool VALUE = true;
  };

  template <typename T>
  struct ContainsType<std::tuple<>, T>
  {
      static const bool VALUE = false;
  };

  // -----

  template <typename Lhs, typename Rhs>
  struct ContainsTypes;

  template <typename Tuple, typename T, typename... Ts>
  struct ContainsTypes<Tuple, std::tuple<T, Ts...>>
  {
      static const bool VALUE = ContainsType<Tuple, T>::VALUE && ContainsTypes<Tuple, std::tuple<Ts...>>::VALUE;
  };

  template <typename Tuple>
  struct ContainsTypes<Tuple, std::tuple<>>
  {
      static const bool VALUE = true;
  };
like image 23
Maarten Bamelis Avatar answered Sep 21 '22 08:09

Maarten Bamelis