7. Class operators #
Operators can be added to your custom types, this is done via the wren::ForeignMethodOperator enumeration.
This is a list of all supported operators by WrenBind17:
| Operator | Enum Value | 
|---|---|
| Add (+) | OPERATOR_ADD | 
| Subtract (-) | OPERATOR_SUB | 
| Multiply (*) | OPERATOR_MUL | 
| Divide (/) | OPERATOR_DIV | 
| Unary negative (-) | OPERATOR_NEG | 
| Modulo (%) | OPERATOR_MOD | 
| Equal to (==) | OPERATOR_EQUAL | 
| Not equal to (!=) | OPERATOR_NOT_EQUAL | 
| Greater than (>) | OPERATOR_GT | 
| Less than (<) | OPERATOR_LT | 
| Greather than or equal (>=) | OPERATOR_GT_EQUAL | 
| Less than or equal (<=) | OPERATOR_LT_EQUAL | 
| Shift left («) | OPERATOR_SHIFT_LEFT | 
| Shift right (») | OPERATOR_SHIFT_RIGHT | 
| Binary and (&) | OPERATOR_AND | 
| Binary xor (^) | OPERATOR_XOR | 
| Binary or (|) | OPERATOR_OR | 
| Get by index [] | OPERATOR_GET_INDEX | 
| Set by index [] | OPERATOR_SET_INDEX | 
7.1. Basic usage #
Adding arithemtic or comparison operators can be done in the following way.
class Vec3 {
public:
    Vec3(float x, float y, float z) : x(x), y(y), z(z) {
    }
    Vec3 operator - () const { // Unary negation operator
        ...
    }
    Vec3 operator + (const Vec3& other) const {
        ...
    }
    Vec3 operator - (const Vec3& other) const {
        ...
    }
    Vec3 operator * (const Vec3& other) const {
        ...
    }
    Vec3 operator / (const Vec3& other) const {
        ...
    }
    bool operator == (const Vec3& other) const {
        ...
    }
    bool operator != (const Vec3& other) const {
        ...
    }
    float x;
    float y;
    float z;
};
int main(...) {
    wren::VM vm;
    ...
    // If you don't do this, the compiler will have no idea
    // which operator to use when binding OPERATOR_SUB and OPERATOR_NEG.
    // With this and static_cast you will explicitly tell the compiler
    // which exact function to use.
    typedef Vec3 (Vec3::*Vec3Sub)(const Vec3&) const;
    typedef Vec3 (Vec3::*Vec3Neg)() const;
    // Bind the class and some basic functions/vars
    auto& cls = m.klass<Vec3>("Vec3");
    cls.ctor<float, float, float>(); // Constructor
    cls.var<&Vec3::x>("x");
    cls.var<&Vec3::y>("y");
    cls.var<&Vec3::z>("z");
    // Bind the operators
    cls.func<&Vec3::operator+ >(wren::OPERATOR_ADD);
    cls.func<static_cast<Vec3Sub>(&Vec3::operator-)>(wren::OPERATOR_SUB);
    cls.func<static_cast<Vec3Neg>(&Vec3::operator-)>(wren::OPERATOR_NEG);
    cls.func<&Vec3::operator* >(wren::OPERATOR_MUL);
    cls.func<&Vec3::operator/ >(wren::OPERATOR_DIV);
    cls.func<&Vec3::operator== >(wren::OPERATOR_EQUAL);
    cls.func<&Vec3::operator!= >(wren::OPERATOR_NOT_EQUAL);
}
Afterwards you can use it in the following way:
import "test" for Vec3
var a = Vec3.new(1.0, 2.0, 3.0)
var b = Vec3.new(4.0, 5.0, 6.0)
var c = a + b
Note
If you are using Visual Studio and trying to bind operator
<then you might get an error:error C2833: 'operator >' is not a recognized operator or type. This happens because the compiler is unable to understandcls.func<&Vec3::operator>>(wren::OPERATOR_GT). Simply, put( )around the operator like this:cls.func<(&Vec3::operator>)>(...).
Note
Using
*=,-=,+=, or/=is not allowed. Wren does not support these assignment operators and results in Wren compilation error.
7.2. Operator with multiple types #
Consider the following C++ class:
class Vec3 {
public:
    Vec3 operator * (const Vec3& other) const {
        ...
    }
    Vec3 operator * (const float value) const {
        ...
    }
};
You have two operators but the second one only accepts a single value. This can be useful when you want to, for example, multiply a 3D vector with a constant value. This can be a problem when binding these two operators to Wren. You can’t bind them both, but you can use std::variant<> instead.
Create a new function in the following way:
Vec3 operator * (const std::variant<Vec3, float>& var) const {
    if (var.index() == 0) {
        Vec3 other = std::get<Vec3>(var);
        // Multiply by other vector
    } else {
        float other = std::get<float>(var);
        // Multiply by constant value
    }
}
int main(...) {
    wren::VM vm;
    ...
    auto& cls = m.klass<Vec3>("Vec3");
    cls.ctor<float, float, float>();
    cls.var<&Vec3::x>("x");
    cls.var<&Vec3::y>("y");
    cls.var<&Vec3::z>("z");
    // Optional typedef to explicitly select the correct 
    // operator with the std::variant
    typedef Vec3 (Vec3::*Vec3Mul)(const std::variant<Vec3, float>&) const;
    // Bind the function
    cls.func<static_cast<Vec3Mul>(&Vec3::operator*)>(wren::OPERATOR_MUL);
}
Then, insie of Wren, you can do the following:
import "test" for Vec3
var a = Vec3.new(1.0, 2.0, 3.0)
var b = Vec3.new(4.0, 5.0, 6.0)
// Multiply by the other vector
var c = a + b
// Or multiply by a constant value
var c = a * 1.5