Reputation: 188
Iam using stl set
container class for storing pointers to objects. While reading from the stl sets, for different runs of the program, the order of objects are getting changed because of dynamic allocation of memory (address) to object.
Lets say objects are A,B,C and their addresses in first run are 10,16,12. So when I insert these objects into set and retrieve them, I will get output as A C B (b'caz 10<12<16). Now if in the next run the addresses alloted are 14, 10, 8, I would get the output as C B A (8<10<14).
Is there any way that I can get output in perticular order?
Overloading comparator (custom comparator) can solve the problem, but in that case I have to pass it as a template parameter, which leads to modifying code at many places. Is there any way of avoiding modifying my code, still able to write custome comparator?
Upvotes: 0
Views: 111
Reputation: 153840
Instead of sorting by the value of the pointers, you should probably pass a comparison object sorting by the pointed to values:
struct deref_compare {
template <typename T>
bool operator()(T const* o0, T const* o1) const {
return *o0 < *o1;
}
};
std::set<int*, deref_compare> s;
// use s as before
If you can't change the declaration of the std::set<int*>
you can technically specialize std::less<int*>
to do something different but it isn't allowed unless you specialize involving user-defined types:
namespace std
{
template <>
class less<int*> {
public:
bool operator()(int const* o0, int const* o1) const {
return *o0 < *o1;
}
};
}
Note that specializing any of the standard class templates without involving user-defined types results in undefined behavior: I'd recommend against specializing std::less<int*>
. The problem is that it can affect other code, e.g., in the standard C++ library. The relevant section of the C++ standard is 17.6.4.2.1 [namespace.std] paragraph 1:
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace
std
or to a namespace within namespacestd
unless otherwise specified. A program may add a template specialization for any standard library template to namespacestd
only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.
Upvotes: 3
Reputation: 145279
You can specify a comparison function.
As I'm writing this there is no code in the question, so no way to provide an example using your classes etc.
Just check out the documentation.
Upvotes: 2
Reputation: 133587
Since the order imposed in a std::set
is managed through a natural ordering of the elements, if you need a specific order, you need a specific criterion which doesn't change every specific run. This because the natural ordering on pointers involves just the value of the address itself.
This means that you need to have a way to give a consistent order on them, through a specific comparison operator, eg:
struct my_order {
bool operator() (const Object* lhs, const Object* rhs) const {
// return consistent value for same pair of lhs and rhs
}
set<Object*, my_order> mySet;
Upvotes: 2