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 .firstto the set, as long as their.secondare 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.
 
     
    