Home > Software engineering >  Static assertion if one std::array is a subset of the other
Static assertion if one std::array is a subset of the other

Time:11-28

I'm using two constexpr std::array:

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

I would like to static assert if the second is a subset of the first.

In the above example, the assertion should succeed, and in the following, it supposes to fail:

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

I wrote a working constexpr function:

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;
}

But I wondered if there is another, more straightforward (without decltype, maybe without constexpr function?) way of doing it (latest CPP).

CodePudding user response:

In you can std::ranges::sort both ranges and then applystd::ranges::includes:

Returns true if the sorted range [first2, last2) is a subsequence of the sorted range [first1, last1).

Demo:

constexpr bool is_subset(auto a, auto b) {
    std::ranges::sort(a);
    std::ranges::sort(b);
    return std::ranges::includes(a, b);
}

int main() {
    constexpr std::array full = { 1,3,2 };
    constexpr std::array subset = { 3, 2 };

    static_assert(is_subset(full, subset), "Has to be a subset");
}

CodePudding user response:

Rather than a nest for-loop, or sorting both array, you can also just sort the longer one, and loop on the other one while performing a binary search:

constexpr bool isSubset(auto sup, auto sub)
{
    if (sub.size() > sup.size()) return false;
    std::ranges::sort(sup);
    return std::ranges::all_of(sup, 
        [&](auto i){ return std::ranges::binary_search(sub, i); }
    );
}
  • Related