8

I found a bug in my code where I forgot to use a custom comparator when sorting a container of structs. This made me wonder what it was using as the less than operator, since I didn't define any for the struct.

How do objects compare <, >, and == when those operators aren't defined? Is it by memory address? Is it defined in the standard? I couldn't find any of this information on Google.

EDIT:

Here's the class that I was using:

using namespace std;

typedef unsigned id;

class LogEntry {
    id master_id;
    string timestamp;
    string category;
    string message;
    string str_rep;

public:
    LogEntry(id id, string t, string c, string m) :
            master_id(id), timestamp(t), category(c), message(m) {
    }

    string get_timestamp() const {
        return timestamp;
    }

    string get_category() const {
        return category;
    }

    string get_message() const {
        return message;
    }

    string to_string() {
        ostringstream ss;
        ss << master_id << "|" << timestamp << "|" << category << "|"
                << message;
        return ss.str();
    }

    id get_id() const {
        return master_id;
    }
};

EDIT2:

I realized I made a dumb mistake. I was storing a vector of pointers to the objects. Thus, it's very likely that the pointers are compared by the address. If I hadn't been storing pointers, I don't think it would have compiled.

EDIT3: KerrekSB posted a related interesting link in the comments of his answer that is related: How can pointers be totally ordered?

Community
  • 1
  • 1
gsgx
  • 12,020
  • 25
  • 98
  • 149
  • Sounds strange. I would have expected your code to fail to compile. Perhaps show us a _testcase_ that reproduces this. – Lightness Races in Orbit Nov 15 '12 at 22:14
  • @LightnessRacesinOrbit Oh, I didn't provide a testcase because I thought there was some default... If that's not the case I'll post some code soon. – gsgx Nov 15 '12 at 22:16

1 Answers1

9

The default comparator is the standard template std::less<T>, which just uses x < y for two objects x and y of type T. There are many ways this could work:

  • T is an arithmetic, fundamental type and the built-in operator is used.

  • T is a class type and has a member operator<.

  • There is a free function operator<(T const &, T const &).

  • Your user-defined type has an implicit conversion function to a built-in type which provides a unique path for calling the built-in <.

Additionally, it is possible to specialize std::less for your user-defined type T.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    But if the class doesn't have any `operator<` defined, how would it evaluate `x < y`? – gsgx Nov 15 '12 at 22:18
  • @gsingh2011: In one of the other ways I listed. – Kerrek SB Nov 15 '12 at 22:19
  • 1
    But the class I wrote isn't a fundamental type, and I haven't defined any function that looks like `operator<(T const &, T const &)`. Essentially it looks like `class Foo { int a; string b; }`. – gsgx Nov 15 '12 at 22:21
  • Actually, sorry. There was a boolean function that took two `Foo`s. Is it possible that g++ assumed it was a comparator? – gsgx Nov 15 '12 at 22:23
  • 1
    @gsingh2011: Only if it's called `operator<`. Maybe if your type has an implicit conversion function? [Edit:] Yes, that's it. I added it. – Kerrek SB Nov 15 '12 at 22:24
  • @KerrekSB Do pointers count as arithmetic, fundamental types? – john Nov 15 '12 at 22:50
  • @john : Fundamental, yes; arithmetic, no. – ildjarn Nov 15 '12 at 23:00
  • 1
    @john: [Pointers and `std::less` are a bit special...](http://stackoverflow.com/questions/13380063/how-can-pointers-be-totally-ordered). – Kerrek SB Nov 15 '12 at 23:53
  • The last one "Your user-defined type has an implicit conversion function to a built-in type" is most tricky (it shows how hard-working & smart the compiler is when trying to finish the work). – TingQian LI Jul 06 '21 at 00:50