I need to sort a vector of custom type std::vector<Blah> v
by Blah's integer id. I do this via std::sort(v.begin(), v.end())
with the operator <
being overloaded within Blah
as
bool operator< (const Blah& b) const { return (id < b.id); }
I noticed that Blah's private id cannot be declared as const int id
, otherwise the type Blah
does not meet the requirements for std::sort
(I assume it conflicts with not being ValueSwappable?)
If id
is not const
everything is fine. However, I dislike the idea of the objects not having constant ids just for the requirement of rearranging their order within a vector.
Is there a way around or is this the way it is?
You can sort a vector of custom objects using the C++ STL function std::sort. The sort function has an overloaded form that takes as arguments first, last, comparator. The first and last are iterators to first and last elements of the container.
The vector can use the array notation to access the elements. If you don't want to use the default std::sort , or std::sort with custom comparator, you can use qsort or write your own.
Sorting a vector in C++ can be done by using std::sort(). It is defined in<algorithm> header. To get a stable sort std::stable_sort is used. It is exactly like sort() but maintains the relative order of equal elements.
Is there a way around or is this the way it is?
I fear that this is the way it is. If you want to sort a vector, which is in principle an array, then you have to assign to elements when exchanging them.
At least that is what i thought, actually you can cheat a bit. Wrap your objects into an union:
template<typename T>
union ac {
// actual object
T thing;
// assignment first destructs object, then copy
// constructs a new inplace.
ac & operator=(ac<T> const & other) {
thing. ~T();
new (& thing) T(other. thing);
}
// need to provide constructor, destructor, etc.
ac(T && t) : thing (std:: forward<T>(t))
{}
ac(ac<T> const & other) : thing (other. thing) {}
~ac() {
thing. ~T();
}
// if you need them, add move assignment and constructor
};
You can then implement the (copy) assignment operator to first destruct the current object and then (copy) construct a new object from the provided inplace of the old object.
You also need to provide constructors and destructors, and of course this only works with C++11 and beyond due to limitations concerning the union members in previous language standards.
This seems to work quite nice: Live demo.
But still, I think you should first revisit some design choices, e.g. if the constant id really needs to be part of your objects
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With