I am writing a template function, with template argument X
. Inside that function, I want to create std::set<std::pair<int, X>>
such that:
- objects in that set are sorted by the first (
int
) field of the pair (I don't care about how ties are broken) - I can add multiple objects with the same
.first
to the set, as long as their.second
are not identical
If I knew that template argument X
always has <
defined, the most basic std::set<std::pair<int, X>
(with the default comparator) would have worked perfectly fine. Unfortunately, I cannot assume anything about X
.
I was thinking to "cheat" and use pointer-based comparison for the X
field:
template <typename X>
struct DistCmp {
bool operator()(const std::pair<int, X>& lhs, const std::pair<int, X>& rhs) const {
return lhs.first < rhs.first || lhs.first == rhs.first && &lhs.second < &rhs.second;
}
};
template <typename X>
void f() {
std::set<std::pair<int, X>, DistCmp<X>> s{};
// ...
}
(After all, I don't really care how the .second
is compared, as long as it's not compared equally for non-identical objects.)
Unfortunately, I don't think it's correct. Partly because of the quote from C++ standard here (it suggests that pointer comparison, in general, is unspecified, so I can't rely on them being unequal for non-identical objects). And partly I just feel it's suspicious/hacky.
Is there any clean/portable solution for this issue?
Update:
One approach I thought about was to use ==
for the comparison of pointers instead of <
. However, this is no good because it will cause pair<1, x> < pair<1, y> && pair<1, y> < pair<1, x>
to be true
. This violates the requirement of strict weak ordering and may cause stuff to break.