Operator overloading between different types in Luau?

So basically, I want to know what the best way to overload the == operator would be on tables of two different types.

So like how in C++, you could have this:

#include <iostream>
using namespace std;

class two {
    public:
        int value1;
        two(int v1) {
            value1 = v1;
        }
};

class one {
    public:
        int value2;
        one(int v2) {
            value2 = v2;
        }

        bool operator==(const two& other) const {
            return this->value2 == other.value1;
        };
        bool operator!=(const two& other) const {
            return this->value2 != other.value1;
        };
};

int main() {
    one* obj = new one(3);
    two* obj2 = new two(2);
    
    bool isEqual = *obj == *obj2;
    bool isNotEqual = *obj != *obj2;

    cout << isEqual << endl; //this outputs 0 (false) because their values are different
    cout << isNotEqual << endl; //this outputs 1 (true) because their values are different

    delete obj;
    delete obj2;

    return 0;
}

Is there a way to replicate this behaviour between two different tables via metatables? The closest I’ve got is the __eq metamethod, but it has some odd requirements, like both tables having the same metatable, and both having the __eq metamethod set.

local a = {3}
local b = {3}

local meta = {__eq = function(self: {number}, other: {number}): boolean
	return self[1] == other[1]
end}

setmetatable(a, meta)
setmetatable(b, meta)

print(a == b)

The above snippet seems to be the only snippet that works, even if I use two different metatables with the exact same __eq code content.

Basically, in the C++ example, only one object needs the overload operator and can compare between different types. In the Luau example, both objects need to be of the same type (i.e. have the same elements that are being compared) and the metatables both need to be the same, as in the exact same metatable at the exact same memory location. I could also do it through a separate function, but that kind of defeats the point.

I want to replicate the C++ behaviour so I can compare between types with only one table needing the __eq metamethod set. If anyone has any idea how, please let me know.

Thanks!

Take a look at the solution marked on this thread (slightly different problem but explanation is good)

Setting a metamethod on one of the metatables is probably the easiest work around for this.

Since they both need to have the __eq metamethod and they are different tables, it’s much more hassle to do it with metamethods. I’ve just resorted to the separate function workaround. In my use case, the second table to be compared always comes from the server, and it’s a pain to re-assign metamethods to it each time when the function alternative works better overall.

I think this is the closest I could mimic the C++ code sample ( if it helps anyone ?)

--!strict
local meta = {}
meta.__index = meta

function meta.new(val:number)
	return setmetatable({value = val}, meta)
end

function meta:Compare(other: {value:number}): boolean
	return self.value == other.value
end

local bmeta = {}
bmeta.__index = bmeta

function bmeta.new(val:number)
	return setmetatable({value = val}, bmeta)
end

local a = meta.new(3)
local b = bmeta.new(3)

print(a:Compare(b))  --true

b.value = 4

print(a:Compare(b))  --false

b:Compare(a) --in strict this should be underlined in blue and will error

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.