Operator Overloading¶
This section covers an example of overloading arithmetic and comparison operators. If the target language does not allow some of the operators to be overloaded or we don’t want to overload them in the target language, we can set the is_operator variable to False. We should also specify name for that operator so that the target language uses that name.
/**
* An example for with overloaded methods.
* __API__
* action: gen_class
* package: operators
*/
class Counter {
public:
/**
* Counter constructor.
* __API__
* action: gen_constructor
* throws: no_throw
*/
Counter(int count) : _count(count) {}
Counter(const Counter& c) {
_count = c.count();
}
/**
* Getter for count.
* __API__
* action: gen_getter
* throws: no_throw
*/
int count() const {
return _count;
}
/**
* Plus operator
* __API__
* action: gen_method
* throws: no_throw
*/
Counter operator+(const Counter& counter) {
return Counter(_count + counter.count());
}
/**
* Comparison operator for kotlin
* __API__
* kotlin.action: gen_method
* kotlin.is_operator: True
* kotlin.name: compareTo
* throws: no_throw
*/
int compareTo(const Counter& counter) {
if (_count > counter.count()) return 1;
else if (_count < counter.count()) return -1;
else return 0;
}
/**
* __API__
* python.action: gen_method
* swift.action: gen_method
* throws: no_throw
*/
bool operator>(const Counter& counter) {
return _count > counter.count();
}
/**
* __API__
* python.action: gen_method
* swift.action: gen_method
* throws: no_throw
* return_value_policy: reference
*/
Counter& operator +=(const Counter& counter) {
this->_count += counter.count();
return *this;
}
private:
int _count;
};
Note
All comparisons in Kotlin are translated into calls to compareTo, that is required to return Int.
That’s why we have compareTo method in C++ with kotlin.is_operator set to True(this is mandatory as compareTo is not a C++ operator and by default, is_operator is False for it).
Also notice we do not have Kotlin action for operator>.
Note
For the += operator, we are generating bindings only for Python and Swift because for Kotlin, the signature of this operator is different, and we already have generated binding for the + operator, which also covers the += operator.
And the usage example:
var counter1 = Counter(1)
var counter2 = Counter(2)
var counter = counter1 + counter2
assert(counter.count == 3)
counter += counter1
assert(counter.count == 4)
assert(counter1 < counter2)
assert(counter1 <= counter2)
assert(counter2 > counter1)
assert(counter2 >= counter1)
counter1 = Counter(1)
counter2 = Counter(2)
counter = counter1 + counter2
assert counter.count == 3
assert counter1 < counter2
assert counter2 > counter1
counter1 += counter2
assert counter1.count == 3
let counter1 = Counter(count: 1)
let counter2 = Counter(count: 2)
let counter = counter1 + counter2
assert(counter.count == 3)
assert(counter2 > counter1)
counter1 += counter2
assert(counter1.count == 3)
assert(counter1 > counter2)
Generated operators for target languages
/**
* ______ .______ .______ .______ __ .__ __. _______
* / || _ \ | _ \ | _ \ | | | \ | | | \
* | ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
* | | | ___/ | ___/ | _ < | | | . ` | | | | |
* | `----.| | | | | |_) | | | | |\ | | '--' |
* \______|| _| | _| |______/ |__| |__| \__| |_______/
*
* This file is generated by cppbind on 05/12/2022-10:29.
* Please do not change it manually.
*/
package com.examples.operators
import com.examples.cppbind.alias.*
import com.examples.cppbind.exceptionUtils.*
import com.examples.cppbind.exception_helpers.*
/**
* An example for with overloaded methods.
*/
open class Counter
internal constructor(obj: CppBindObject) : AutoCloseable {
companion object {
init {
System.loadLibrary("wrapper_jni")
}
/**
* Counter constructor.
*/
protected fun construct_helper(count: Int): Long {
val id = jConstructor(count)
return id
}
@JvmStatic
private external fun jConstructor(count: Int): Long
const val cppbindCxxTypeName: String = "cppbind::example::Counter"
}
protected var cppbindObj = obj
private var refs: MutableList<Any> = mutableListOf()
fun keepCppBindReference(ref: Any) {
refs.add(ref)
}
open val id: Long
get() {
if (cppbindObj.id == 0L) {
throw RuntimeException("Object is not allocated")
}
return cppbindObj.id
}
/**
* Counter constructor.
*/
constructor(count: Int): this(CppBindObject(construct_helper(count), true)) {
}
/**
* Getter for count.
*/
val count: Int
get() {
val result = jCount(id)
return result
}
/**
* Plus operator
*/
operator fun plus(counter: Counter): Counter {
val kotlintojdkcounter = counter.id
val result = jPlus(id, kotlintojdkcounter)
val jdktokotlinresult = Counter(CppBindObject(result, true))
return jdktokotlinresult
}
/**
* Comparison operator for kotlin
*/
operator fun compareTo(counter: Counter): Int {
val kotlintojdkcounter = counter.id
val result = jCompareto(id, kotlintojdkcounter)
return result
}
override fun close() {
if (cppbindObj.owner && cppbindObj.id != 0L) {
jFinalize(cppbindObj.id)
cppbindObj.id = 0L
}
}
/**
* Finalize and deletes the object
*/
protected fun finalize() {
close()
}
///// External wrapper functions ////////////
private external fun jCount(id: Long): Int
private external fun jPlus(id: Long, counter: Long): Long
private external fun jCompareto(id: Long, counter: Long): Int
private external fun jFinalize(id: Long): Unit
}
private external fun jGettypebyid(id: Long): String
"""
______ .______ .______ .______ __ .__ __. _______
/ || _ \ | _ \ | _ \ | | | \ | | | \
| ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
| | | ___/ | ___/ | _ < | | | . ` | | | | |
| `----.| | | | | |_) | | | | |\ | | '--' |
\______|| _| | _| |______/ |__| |__| \__| |_______/
This file is generated by cppbind on 05/12/2022-10:33.
Please do not change it manually.
"""
from __future__ import annotations
from typing import *
import examples.operators.counter as pybind_counter_pygen
from examples_lib.cppbind.bind_utils_pygen import *
from examples_lib.cppbind.metaclass_pygen import *
class Counter(metaclass=CppBindMetaclass):
"""
An example for with overloaded methods.
Documentation generated from: `cxx/operators/counter.hpp#L12
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/counter.hpp#L12>`_
"""
@bind
def __init__(self, count: int):
"""
Counter constructor.
Documentation generated from: `cxx/operators/counter.hpp#L20
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/counter.hpp#L20>`_
"""
pass
@property
@bind
def count(self) -> int:
"""
Getter for count.
Documentation generated from: `cxx/operators/counter.hpp#L32
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/counter.hpp#L32>`_
"""
pass
@bind
def __add__(self, counter: Counter) -> Counter:
"""
Plus operator
Documentation generated from: `cxx/operators/counter.hpp#L42
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/counter.hpp#L42>`_
"""
pass
@bind
def __gt__(self, counter: Counter) -> bool:
"""
Documentation generated from: `cxx/operators/counter.hpp#L66
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/counter.hpp#L66>`_
"""
pass
@bind
def __iadd__(self, counter: Counter) -> Counter:
"""
Documentation generated from: `cxx/operators/counter.hpp#L77
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/counter.hpp#L77>`_
"""
pass
/**
* ______ .______ .______ .______ __ .__ __. _______
* / || _ \ | _ \ | _ \ | | | \ | | | \
* | ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
* | | | ___/ | ___/ | _ < | | | . ` | | | | |
* | `----.| | | | | |_) | | | | |\ | | '--' |
* \______|| _| | _| |______/ |__| |__| \__| |_______/
*
* This file is generated by cppbind on 05/12/2022-10:26.
* Please do not change it manually.
*/
import CWrapper
import Foundation
/**
* An example for with overloaded methods.
*/
public class Counter {
public let cself: CppBindCObject
public let owner: Bool
private var refs: [Any]
/// internal main initializer
internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
self.cself = _cself
self.owner = _owner
self.refs = []
}
deinit {
release_CppbindExample_Counter(cself, owner)
}
public func keepCppBindReference(_ object: Any) {
self.refs.append(object)
}
/**
* Counter constructor.
*/
public convenience init(count: Int) {
let swifttosccount = CInt(count)
var cppbindErr = CppBindCObject()
self.init(create_CppbindExample_Counter(swifttosccount, &cppbindErr), true)
if cppbindErr.type != nil {
let errorType = String(cString: cppbindErr.type!)
switch errorType {
case ("std::exception"):
let excObj = StdException(cppbindErr, true)
ExceptionHandler.handleUncaughtException(excObj.what())
default:
cppbindErr.type.deallocate()
ExceptionHandler.handleUncaughtException("Uncaught Exception")
}
}
}
/**
* Getter for count.
*/
public var count: Int {
var cppbindErr = CppBindCObject()
let result = _prop_get_CppbindExample_Counter_count(cself, &cppbindErr)
if cppbindErr.type != nil {
let errorType = String(cString: cppbindErr.type!)
switch errorType {
case ("std::exception"):
let excObj = StdException(cppbindErr, true)
ExceptionHandler.handleUncaughtException(excObj.what())
default:
cppbindErr.type.deallocate()
ExceptionHandler.handleUncaughtException("Uncaught Exception")
}
}
let sctoswiftresult = Int(result)
return sctoswiftresult
}
/**
* Plus operator
*/
public static func +(cself: Counter, counter: Counter) -> Counter {
let swifttosccounter = counter.cself
var cppbindErr = CppBindCObject()
let result = _func_CppbindExample_Counter__add_(cself.cself, swifttosccounter, &cppbindErr)
if cppbindErr.type != nil {
let errorType = String(cString: cppbindErr.type!)
switch errorType {
case ("std::exception"):
let excObj = StdException(cppbindErr, true)
ExceptionHandler.handleUncaughtException(excObj.what())
default:
cppbindErr.type.deallocate()
ExceptionHandler.handleUncaughtException("Uncaught Exception")
}
}
var sctoswiftresult: Counter
sctoswiftresult = Counter(result, true)
return sctoswiftresult
}
public static func >(cself: Counter, counter: Counter) -> Bool {
let swifttosccounter = counter.cself
var cppbindErr = CppBindCObject()
let result = _func_CppbindExample_Counter__gt_(cself.cself, swifttosccounter, &cppbindErr)
if cppbindErr.type != nil {
let errorType = String(cString: cppbindErr.type!)
switch errorType {
case ("std::exception"):
let excObj = StdException(cppbindErr, true)
ExceptionHandler.handleUncaughtException(excObj.what())
default:
cppbindErr.type.deallocate()
ExceptionHandler.handleUncaughtException("Uncaught Exception")
}
}
return result
}
public static func +=(cself: Counter, counter: Counter) -> Counter {
let swifttosccounter = counter.cself
var cppbindErr = CppBindCObject()
let result = _func_CppbindExample_Counter__iadd_(cself.cself, swifttosccounter, &cppbindErr)
if cppbindErr.type != nil {
let errorType = String(cString: cppbindErr.type!)
switch errorType {
case ("std::exception"):
let excObj = StdException(cppbindErr, true)
ExceptionHandler.handleUncaughtException(excObj.what())
default:
cppbindErr.type.deallocate()
ExceptionHandler.handleUncaughtException("Uncaught Exception")
}
}
var sctoswiftresult: Counter
sctoswiftresult = Counter(result)
return sctoswiftresult
}
class var cppbindCxxTypeName : String { return "cppbind::example::Counter" }
}
Overloading subscript operator¶
Here is the example of overloading operator[].
/**
* An example for with overloaded operators.
* __API__
* action: gen_interface
* package: operators
*/
class IntArray {
public:
/**
* __API__
* action: gen_constructor
* throws: no_throw
*/
IntArray() {
for(int i = 0; i < SIZE; i++) {
arr[i] = i;
}
}
/**
* __API__
* action: gen_method
* throws: no_throw
*/
int& operator[](int i) {
if( i > SIZE ) {
return arr[0];
}
return arr[i];
}
/**
* __API__
* action: gen_method
* throws: no_throw
*/
const int& operator[](std::string i) {
int ii = std::stoi(i);
if( ii > SIZE ) {
return arr[0];
}
return arr[ii];
}
/**
* __API__
* action: gen_method
* throws: no_throw
*/
int operator[](double i) {
int ii = static_cast<int>(i);
if( ii > SIZE ) {
return arr[0];
}
return arr[ii];
}
private:
int arr[10];
};
Usage example:
var intArr = IntArrayImpl()
assert(intArr[0] == 0)
assert(intArr[9] == 9)
assert(intArr["9"] == 9)
assert(intArr[9.0] == 9)
intArr[9] = 10
assert(intArr[9] == 10)
assert(intArr["9"] == 10)
assert(intArr[9.0] == 10)
intArr = IntArray()
assert (intArr[0] == 0)
assert (intArr[9] == 9)
assert (intArr["9"] == 9)
assert (intArr[9.0] == 9)
intArr[9] = 10
assert (intArr[9] == 10)
assert (intArr["9"] == 10)
assert (intArr[9.0] == 10)
var intArr = IntArrayImpl()
assert(intArr[0] == 0)
assert(intArr[9] == 9)
assert(intArr["9"] == 9)
assert(intArr[9.0] == 9)
intArr[9] = 10
assert(intArr[9] == 10)
assert(intArr["9"] == 10)
assert(intArr[9.0] == 10)
Overloaded subscript operators for target languages
/**
* ______ .______ .______ .______ __ .__ __. _______
* / || _ \ | _ \ | _ \ | | | \ | | | \
* | ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
* | | | ___/ | ___/ | _ < | | | . ` | | | | |
* | `----.| | | | | |_) | | | | |\ | | '--' |
* \______|| _| | _| |______/ |__| |__| \__| |_______/
*
* This file is generated by cppbind on 05/12/2022-10:29.
* Please do not change it manually.
*/
package com.examples.operators
import com.examples.cppbind.alias.*
import com.examples.cppbind.exceptionUtils.*
import com.examples.cppbind.exception_helpers.*
/**
* An example for with overloaded operators.
*/
interface IIntArray : AutoCloseable {
val id: Long
fun keepCppBindReference(ref: Any)
operator fun get(i: Int): Int {
val result = IIntArrayHelper.jGet(id, i)
return result
}
operator fun set(i: Int, value: Int){
IIntArrayHelper.jSet(id, i, value)
}
operator fun get(i: String): Int {
val result = IIntArrayHelper.jGet_1(id, i)
return result
}
operator fun get(i: Double): Int {
val result = IIntArrayHelper.jGet_2(id, i)
return result
}
}
class IIntArrayHelper {
companion object {
@JvmStatic
external fun jGet(id: Long, i: Int): Int
@JvmStatic
external fun jSet(id: Long, i: Int, value: Int)
@JvmStatic
external fun jGet_1(id: Long, i: String): Int
@JvmStatic
external fun jGet_2(id: Long, i: Double): Int
}
}
open class IntArrayImpl
internal constructor(obj : CppBindObject) : IIntArray {
companion object {
init {
System.loadLibrary("wrapper_jni")
}
protected fun construct_helper(): Long {
val id = jConstructor()
return id
}
@JvmStatic
private external fun jConstructor(): Long
const val cppbindCxxTypeName: String = "cppbind::example::IntArray"
}
protected var cppbindObj = obj
private var refs: MutableList<Any> = mutableListOf()
override fun keepCppBindReference(ref: Any) {
refs.add(ref)
}
override val id: Long
get() {
if (cppbindObj.id == 0L) {
throw RuntimeException("Object is not allocated")
}
return cppbindObj.id
}
constructor(): this(CppBindObject(construct_helper(), true)) {
}
override fun close() {
if (cppbindObj.owner && cppbindObj.id != 0L) {
jFinalize(cppbindObj.id)
cppbindObj.id = 0L
}
}
/**
* Finalize and deletes the object
*/
protected fun finalize() {
close()
}
///// External wrapper functions ////////////
private external fun jFinalize(id: Long): Unit
}
private external fun jGettypebyid(id: Long): String
"""
______ .______ .______ .______ __ .__ __. _______
/ || _ \ | _ \ | _ \ | | | \ | | | \
| ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
| | | ___/ | ___/ | _ < | | | . ` | | | | |
| `----.| | | | | |_) | | | | |\ | | '--' |
\______|| _| | _| |______/ |__| |__| \__| |_______/
This file is generated by cppbind on 05/12/2022-10:33.
Please do not change it manually.
"""
from __future__ import annotations
from typing import *
import examples.operators.intarray as pybind_intarray_pygen
from examples_lib.cppbind.bind_utils_pygen import *
from examples_lib.cppbind.metaclass_pygen import *
class IntArray(metaclass=CppBindMetaclass):
"""
An example for with overloaded operators.
Documentation generated from: `cxx/operators/intarray.hpp#L16
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/intarray.hpp#L16>`_
"""
@bind
def __init__(self):
"""
Documentation generated from: `cxx/operators/intarray.hpp#L23
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/intarray.hpp#L23>`_
"""
pass
@bind
def __getitem__(self, i: int) -> int:
"""
Documentation generated from: `cxx/operators/intarray.hpp#L34
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/intarray.hpp#L34>`_
"""
pass
@bind
def __setitem__(self, i: int, value: int):
"""
Documentation generated from: `cxx/operators/intarray.hpp#L34
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/intarray.hpp#L34>`_
"""
pass
@bind
def __getitem__(self, i: str) -> int:
"""
Documentation generated from: `cxx/operators/intarray.hpp#L46
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/intarray.hpp#L46>`_
"""
pass
@bind
def __getitem__(self, i: float) -> int:
"""
Documentation generated from: `cxx/operators/intarray.hpp#L59
<https://github.com/PicsArt/cppbind/tree/master/examples/primitives/cxx/operators/intarray.hpp#L59>`_
"""
pass
/**
* ______ .______ .______ .______ __ .__ __. _______
* / || _ \ | _ \ | _ \ | | | \ | | | \
* | ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
* | | | ___/ | ___/ | _ < | | | . ` | | | | |
* | `----.| | | | | |_) | | | | |\ | | '--' |
* \______|| _| | _| |______/ |__| |__| \__| |_______/
*
* This file is generated by cppbind on 05/12/2022-10:26.
* Please do not change it manually.
*/
import CWrapper
import Foundation
/**
* An example for with overloaded operators.
*/
public protocol IntArray {
var cself: CppBindCObject { get }
func keepCppBindReference(_ object: Any)
subscript(i: Int) -> Int { get set }
subscript(i: String) -> Int { get }
subscript(i: Double) -> Int { get }
}
extension IntArray {
public subscript(i: Int) -> Int {
get {
let swifttosci = CInt(i)
let result = _func_CppbindExample_IntArray__getitem_(cself, swifttosci)
let sctoswiftresult = Int(result)
return sctoswiftresult
}
set(value) {
let swifttosci = CInt(i)
let swifttoscvalue = CInt(value)
_func_CppbindExample_IntArray__setitem_(cself, swifttosci, swifttoscvalue)
}
}
public subscript(i: String) -> Int {
let swifttosci = strdup(i)!
let result = _func_CppbindExample_IntArray__getitem__1(cself, swifttosci)
let sctoswiftresult = Int(result)
return sctoswiftresult
}
public subscript(i: Double) -> Int {
let result = _func_CppbindExample_IntArray__getitem__2(cself, i)
let sctoswiftresult = Int(result)
return sctoswiftresult
}
}
public class IntArrayImpl: IntArray {
public let cself: CppBindCObject
public let owner: Bool
private var refs: [Any]
// internal main initializer
internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
self.cself = _cself
self.owner = _owner
self.refs = []
}
deinit {
release_CppbindExample_IntArrayImpl(cself, owner)
}
public func keepCppBindReference(_ object: Any) {
self.refs.append(object)
}
public convenience init() {
var cppbindErr = CppBindCObject()
self.init(create_CppbindExample_IntArray(&cppbindErr), true)
if cppbindErr.type != nil {
let errorType = String(cString: cppbindErr.type!)
switch errorType {
case ("std::exception"):
let excObj = StdException(cppbindErr, true)
ExceptionHandler.handleUncaughtException(excObj.what())
default:
cppbindErr.type.deallocate()
ExceptionHandler.handleUncaughtException("Uncaught Exception")
}
}
}
class var cppbindCxxTypeName : String { return "cppbind::example::IntArray" }
}
Note
As we can see, we have only generated one set operator. It is the case when the return value of the overloaded subscript operator is a non-const-qualified reference.