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.
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.
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.
If all the values of a set, A, are also contained in a larger set, B, then A is a subset of B.
#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
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;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With