【问题标题】:Check if one set of types is subsets with composition检查一组类型是否是具有组合的子集
【发布时间】:2018-06-13 13:34:31
【问题描述】:

我必须检查给定的两个元组是否是另一个元组的子集。我找到了这个优雅的解决方案Check if one set of types is a subset of the other

但是这个解决方案的问题是它没有考虑子类型,例如

using t1 = std::tuple<int, double>;
using t2 = std::tuple<double, int>;
using t3 = std::tuple<t1, t2>;

这将使子集测试失败。

#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...> && ...);

原因是如果我们在 t1 和 t3 上做子集,包含表达式将 int 与 t1 进行比较失败。所以需要改变的是 contains 函数来搜索子类型。

P.S 此代码仅适用于 C++17

【问题讨论】:

    标签: c++ tuples c++17


    【解决方案1】:

    如果您对元组嵌套的结构不感兴趣,您可以“展平”嵌套元组。这意味着

    int main() {
      using t1 = std::tuple<int, double>;
      using t2 = std::tuple<double, int>;
      using t3 = std::tuple<t1, t2>;
    
      static_assert(
        std::is_same<
          flatten<t3>,
          std::tuple<int, double, double, int>
        >{}
      );
    
      static_assert(false == is_subset_of<t1, t3>);
      static_assert(true == is_subset_of< t1, flatten<t3> >);
    
      return 0;
    }
    

    flatten 的快速而简单的实现可能如下所示。

    namespace detail {
    
    template<class... Ts>
    struct flatten {
      static_assert(sizeof...(Ts) == 0, "recursion break (see specializations)");
    
      template<class... Result>// flattened types are accumulated in this pack
      using type = std::tuple<Result...>;
    };
    
    template<template<class...> class Nester, class... Nested, class... Ts>
    struct flatten<Nester<Nested...>, Ts...> {// if first arg is nested then unpack
      template<class... Result>
      using type = typename flatten<Nested..., Ts...>::template type<Result...>;
    };
    
    template<class T0, class... Ts>
    struct flatten<T0, Ts...> {// if `T0` is flat then just append it to `Result...`
      template<class... Result>
      using type = typename flatten<Ts...>::template type<Result..., T0>;
    };
    
    };// detail
    
    template<class... Ts>
    using flatten = typename detail::flatten<Ts...>::template type<>;
    

    【讨论】:

      猜你喜欢
      • 2017-07-23
      • 2016-04-11
      • 2010-09-24
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 2021-10-26
      • 2012-05-20
      • 1970-01-01
      相关资源
      最近更新 更多