You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用更简洁方式静态断言一个std::array是另一个的子集?

静态判断constexpr std::array是否为子集的简洁实现

我有两个constexpr std::array:

constexpr std::array full = { 1,2,3 };
constexpr std::array subset = { 3 };

需要用静态断言判断第二个数组是否是第一个的子集——上面的例子断言应该成功,而下面的例子断言应该失败:

constexpr std::array full = { 1,2,3 };
constexpr std::array subset = { 3, 4 };

我已经写了一个可用的constexpr函数:

constexpr bool isSubset(decltype(full)& a, decltype(subset)& b)
{
    for (const auto& subsetElement : b) {
        bool found = false;
        for (const auto& fullElement : a) {
            if (subsetElement == fullElement) {
                found = true;
                break;
            }
        }
        if (!found) {
            return false;
        }
    }
    return true;
}

但想知道在最新C++标准下有没有更简洁的实现方式,比如不用decltype,甚至不用constexpr函数。


方法1:C++20范围库简化通用constexpr函数

可以将函数改成通用模板,摆脱对具体数组类型的依赖,同时用std::ranges::any_of简化内层循环逻辑:

#include <array>
#include <ranges>

template<typename T, std::size_t N, std::size_t M>
constexpr bool isSubset(const std::array<T, N>& full, const std::array<T, M>& subset)
{
    return std::ranges::all_of(subset, [&full](const auto& elem) {
        return std::ranges::any_of(full, [&elem](const auto& full_elem) {
            return elem == full_elem;
        });
    });
}

// 使用示例
constexpr std::array full = {1,2,3};
constexpr std::array subset = {3};
static_assert(isSubset(full, subset)); // 断言成功

constexpr std::array bad_subset = {3,4};
static_assert(!isSubset(full, bad_subset)); // 断言成功

这个版本通用性更强,无需decltype,借助C++20范围算法让代码更简洁,同时保留编译期计算能力。

方法2:C++20 constexpr lambda直接嵌入静态断言

如果不想单独定义函数,可直接在static_assert中使用constexpr lambda完成判断逻辑,代码更紧凑:

#include <array>
#include <ranges>

constexpr std::array full = {1,2,3};
constexpr std::array subset = {3};
static_assert([&]() constexpr {
    return std::ranges::all_of(subset, [&](const auto& elem) {
        return std::ranges::any_of(full, [&](const auto& fe) { return elem == fe; });
    });
}()); // 断言成功

constexpr std::array bad_subset = {3,4};
static_assert(![&]() constexpr {
    return std::ranges::all_of(bad_subset, [&](const auto& elem) {
        return std::ranges::any_of(full, [&](const auto& fe) { return elem == fe; });
    });
}()); // 断言成功

方法3:C++23 std::ranges::contains进一步简化

C++23新增的std::ranges::contains可以替代内层的any_of,让代码可读性更高、逻辑更直白:

#include <array>
#include <ranges>

template<typename T, std::size_t N, std::size_t M>
constexpr bool isSubset(const std::array<T, N>& full, const std::array<T, M>& subset)
{
    return std::ranges::all_of(subset, [&full](const auto& elem) {
        return std::ranges::contains(full, elem);
    });
}

// 或者直接在断言中使用
constexpr std::array full = {1,2,3};
constexpr std::array subset = {3};
static_assert(std::ranges::all_of(subset, [&](const auto& elem) {
    return std::ranges::contains(full, elem);
}));

内容的提问来源于stack exchange,提问作者AK87

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 01:15:52