c++ - 检查一组类型是否是具有组合的子集
问题描述
我必须检查给定的两个元组一个是否是另一个的子集。我找到了这个优雅的解决方案检查一组类型是否是另一组的子集。
但是这个解决方案的问题是它不考虑子类型,例如
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 上做子集,contains 表达式将 int 与 t1 进行比较失败。所以需要的改变是包含搜索子类型的函数。
PS 此代码仅适用于 C++17
解决方案
如果您对元组嵌套的结构不感兴趣,您可以“展平”嵌套的元组。这意味着
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<>;
推荐阅读
- c# - C# 代码无法在 DLL 中“找到”导出的函数,在 C++ 测试程序中工作
- javascript - Javascript中的文本数组到数组
- php - 远程 MySQL 服务器没有响应
- javascript - 使用 v-if 隐藏和显示元素
- sql - 以 7 位数字结尾的字段的 Big Query SQL 正则表达式
- regex - 使正则表达式与 sed 一起使用以捕获 git repo 名称
- node.js - 为什么this.props.param.match.id未定义,导致Express报错?
- php - 如何在 WordPress 主题中创建指向页面的链接
- node.js - 猫鼬快递计数器不增加,范围问题
- asp.net-mvc - 使用带有实体框架、UnityConfig 和多租户的 ASP.NET MVC 处理 DB 事务/DbContext