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 c 20 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); }
);
}