检查一组类型是否是另一组的子集

Tob*_*ann 17 c++ templates template-meta-programming variadic-templates c++11

如何检查一个参数包(解释为一组)是否是另一个参数包的子集?

到目前为止,我只有框架(使用std :: tuple),但没有功能.

#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");
}
Run Code Online (Sandbox Code Playgroud)

每个类型不允许在一个集合中出现多次.

如果解决方案适用于C++ 11,那将是很好的.

Pio*_*cki 22

#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...> && ...);
Run Code Online (Sandbox Code Playgroud)

DEMO

  • 可能会提供信息,只能从C++ 17开始.但这是迄今为止最优雅的解决方案! (2认同)
  • 你可以在没有递归的情况下编写`contains`; `contains = std :: is_same <T,Ts> :: value || ......;`反过来,它会让你在没有`contains`的情况下编写`is_subset_of`.我不认为我可以写"是一个递增的子集序列",但没有递归或抽象. (2认同)

Maa*_*lis 7

如果您可以使用C++ 17功能,我强烈建议您使用Piotr Skotnicki的解决方案!

我不得不在不久前实现这个功能.我只是要复制粘贴我在那时提出的代码.

我并不是说这是实施这种检查的最佳或最优雅的方式!我没有太多考虑边缘情况; 您可能需要调整代码以满足您的要求.

澄清:ContainsTypes<Lhs, Rhs>检查if是否Rhs是其子集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;
  };
Run Code Online (Sandbox Code Playgroud)