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.