Say I have a set with a comparator like this:
struct prefix_comparator {
using is_transparent = void;
struct prefix {
std::string_view of;
};
bool operator()(std::string_view l, std::string_view r) const {
return l < r;
}
bool operator()(std::string_view l, prefix r) const {
// Only compare up to the size of the prefix
auto result = l.compare(0, r.of.length(), r.of);
return result < 0;
}
bool operator()(prefix l, std::string_view r) const {
auto result = r.compare(0, l.of.length(), l.of);
return result > 0;
}
};
So prefix_comparator::prefix{ "XYZ" } compares equivalent to any string starting with "XYZ" with this comparator. Would it be UB to use this in a std::set?
It does not form equivalence classes with things of type prefix_comparator::prefix, since prefix objects cannot be compared with each other and stuff like equiv("XYZABC", prefix{ "XYZ" }) && equiv(prefix{ "XYZ" }, "XYZabc") but not equiv("XYZABC", "XYZabc"). But the set doesn't store prefix objects, so I don't know if this applies.
It seems to work fine in practice (with libstdc++ std::set): count() returns the correct value greater than 1, equal_range can return an iterator range larger than one element, etc. I'm unsure if find is usable since it only returns an iterator to a single element (possibly it only returns an arbitrary element?)