Vinay
Vinay

Reputation: 188

Order of items in STL SET differ for different runs of program

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

Answers (3)

Dietmar K&#252;hl
Dietmar K&#252;hl

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 namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std 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

Cheers and hth. - Alf
Cheers and hth. - Alf

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

Jack
Jack

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

Related Questions