-1
    struct Data
    {
        std::string Info; // Object Info
        virtual bool operator==(Data& b)
        {
            return this->Info == b.Info;
        }
    };

    struct Data1: public Data
    {
        int ID;
        virtual bool operator==(Data1& b) override // overrides the bool operator==(Data& b) base function
        {
            return (this->Info == b.Info) && (this->ID);
        }
    };

The above code won't compile, I am wandering if it is possible to do so?

I would like my virtual operator function not be class bound.

In other words, maybe something like a template virtual (doesn't exist). I have tried template but of course virtual cannot be paired with template.

   struct Data
    {
        std::string Info; // Object Info
        template <class T>
        virtual bool operator==(T& b)
        {
            return this->Info == b.Info; // something along the line
        }
    };

    struct Data1: public Data
    {
        int ID;
        virtual bool operator==(Data1& b) override // overrides the bool operator==(Data& b) base function
        {
            return (this->Info == b.Info) && (this->ID);
        }
    };

  • 2
    To do what exactly? What is a "class bound" operator? Please add some code that uses `operator==`. – Evg Mar 15 '22 at 08:02
  • The function signatures are different. Related: https://stackoverflow.com/q/49465254 – Ch3steR Mar 15 '22 at 08:04
  • 1
    `operator==` in `Data1` will only work to compare with another `Data1`. What should happen here if you compare a `Data` with a `Data1`, or `Data2`? – super Mar 15 '22 at 08:05
  • 2
    The usual question that arises here is whether it really even makes sense to compare to things of different types. How would a dog equal a rainbow or a sand equal a computer? In most cases, for two things to be equal, they pretty much have to be the same kind of thing. – Jerry Coffin Mar 15 '22 at 08:14
  • 4
    Virtual operators are pretty much useless. If you have `Data a; Data1 b;`, `a == b` and `b == a` mean different things. – molbdnilo Mar 15 '22 at 08:25
  • @Evg operator == when virtual has to specify the input's class. You cannot use the template to do so. – jojo_Aero_smith_the_dummy Mar 15 '22 at 08:27
  • But why do you want to have a virtual `operator==` to begin with? – Evg Mar 15 '22 at 08:29
  • @Evg when do == operation with Data1 I want the function to call the overridden version. – jojo_Aero_smith_the_dummy Mar 15 '22 at 08:30
  • 1
    It does not work like that. You'll fare better with non-member operator utilizing some kind of Double Dispatch on compared objects. – Revolver_Ocelot Mar 15 '22 at 09:04
  • polymorphic types are hardly ever value types. value types can be compared. if you see polymorphic types as values expect pain, a lot of pain. – alfC Mar 15 '22 at 16:45

2 Answers2

1

As a rule, objects of different types can't be equal to each other.

That being the case, for your case, you may be able to get at least reasonably sane results with code on this general order:

struct base {
    std::string info;
    virtual ~base() = default;

    virtual bool cmp(base const& other) const {
        return info == other.info;
    }
};

struct derived1 : public base {
    int i = 0;

    bool cmp(base const& other) const override
    {
        try {
            derived1 const& d = dynamic_cast<derived1 const&>(other);
            return info == d.info && i == d.i;
        }
        catch(...) { return false; }
    }
};

bool operator==(base const &a, base const &b) { 
    return a.cmp(b) && b.cmp(a);
}

The logic here may not be obvious. Instead of overloading == as a virtual member function, we do the overload as a free function. And the free function does two comparisons, once in each order.

We do that to deal with a case like:

base b;
derived1 d;

if (b == d) std::cout << "oops: shouldn't be equal\n";

If we had overloaded operator== as a member function, it would tell us that the two objects are equal, which is almost certainly not desired. It does that because the code is equivalent to: if (b.operator==(d)), which uses the base class comparison operator. Since a reference to the base can refer to an object of derived type, that works, and just compares the base class parts of the two objects, ignoring the fact that one is really a derived object, so the two can't be equal.

With the code the way it's written above, we use both b.operator==(d) and d.operator==(b), so if one of b or d is an object of derived type, then we'll only get a true result if the other is also of the (same) derived type. Any attempt at mixing objects of base and derived type will yield false.

So that does what I think you're asking for. But I'm a long ways from excited about this code even at best. First of all, if comparisons are expensive, it'll get pretty slow, since it does each comparison twice. Second, the code is fragile and difficult to maintain--at the very least, it requires a fairly detailed comment about why it's written the way it is, and why simpler, more obvious code won't work reliably.

Bottom line: yes it works (at least as I perceive what you want), but no I don't like or recommend it.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • As a rule of thumb, exceptions in C++ should be "the exception", i.e. not expected to be frequent. If you expect different types to be compared for equality, then I would recommend using the pointer version of `dynamic_cast(&other)` and return false if the pointer is null. – Jorge Bellon Mar 15 '22 at 10:11
  • @JorgeBellon: ...but in most cases, I'd probably consider comparing mismatched types to be a true error. I've caught it here primarily to have a relatively self-contained example. More often, I'd prefer a fast, noisy crash so the code leading to that gets found and fixed. – Jerry Coffin Mar 15 '22 at 15:04
  • @JerryCoffin yes, the case where a derived class can be equal to base case would cause a serious issue, it would be a even more of a issue when allowed to test the equating of two different derived class since they inherent from the same base class. thank you very much your answer answers my question. – jojo_Aero_smith_the_dummy Mar 16 '22 at 06:17
-1

You need to static_cast Data1 to Data before comparing it's working in my Compiler

struct Data1 : Data {
  int ID;
  // cast before compare
  bool operator==(Data &b) override {
      return  static_cast<const Data&>(*this).Info == b.Info && this->ID;
  }
};
zain ul din
  • 1
  • 1
  • 2
  • 23