Skip to content

Templates

This section covers function and class templates. To generate bindings for function and class templates, we specify all expected values of template parameters. CppBind provides two variables: template and template_instance, to specify all template instantiations which should be exposed to target languages. The value of template variable is a mapping between template parameters and their expected arguments, in this case CppBind deduces all combinations of template arguments, while the value of template_instance is a list of all instantiations.

Note

template and template_instance cannot be used together.

Let's see an example using template variable:

/**
 * __API__
 * action: gen_class
 * package: templates
 */
class TemplateMethods  {
    public:
    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    TemplateMethods() {};

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * template:
     *   T:
     *     - type: int
     *     - type: std::string
     */
    template <typename T>
    T const& max(T const& a, T const& b) {
       return a < b ? b:a;
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * template:
     *   V:
     *     - type: cppbind::example::Project
     *   T:
     *     - type: cppbind::example::Project
     *     - type: cppbind::example::Root
     * return_value_policy: reference
     */
    template <typename T, typename V>
    std::pair<T*, V*> makePair(T* a, V* b) {
       return std::make_pair(a, b);
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * template:
     *   T:
     *     - type: int
     *     - type: std::string
     */
    template <typename T>
    static std::vector<T> merge(const std::vector<T>& first, const std::vector<T>& second) {
        std::vector<T> v(first);
        std::copy(second.begin(), second.end(), std::back_inserter(v));
        return v;
    }
};

Here we have three template member functions: max, makePair and merge. As you can see, we have specified all types for each parameter that should be exposed to target languages. CppBind generates overloaded methods in target languages with each combination of template arguments.

Note

We specified the template argument's type full name in __API__, i.e., cppbind::, not just Task. It is mandatory; otherwise, CppBind cannot find the required information about the specified type.

Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/18/2022-11:03.
 * Please do not change it manually.
 */

package com.examples.templates

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*
import com.examples.simple.Project
import com.examples.simple.Root

open class TemplateMethods
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long

        @JvmName("mergeInt")
        fun merge(first: List<Int>, second: List<Int>): List<Int> {
            val kotlintojdkfirst = IntArray(first.size) 
            var indexFirst = 0
            for (valueFirst in first) {

                kotlintojdkfirst[indexFirst] = valueFirst
                ++indexFirst
            }
            val kotlintojdksecond = IntArray(second.size) 
            var indexSecond = 0
            for (valueSecond in second) {

                kotlintojdksecond[indexSecond] = valueSecond
                ++indexSecond
            }
            val result = jMergeInt(kotlintojdkfirst, kotlintojdksecond, first, second)
            val jdktokotlinresult: MutableList<Int> = mutableListOf()
            for (valueResult in result) {

                jdktokotlinresult.add(valueResult)
            }
            return jdktokotlinresult
        }
        @JvmStatic
        private external fun jMergeInt(first: IntArray, second: IntArray, vararg extraObjs: Any?): IntArray

        @JvmName("mergeString")
        fun merge(first: List<String>, second: List<String>): List<String> {
            val kotlintojdkfirst = ObjectArray(first.size) { Any() }
            var indexFirst = 0
            for (valueFirst in first) {

                kotlintojdkfirst[indexFirst] = valueFirst
                ++indexFirst
            }
            val kotlintojdksecond = ObjectArray(second.size) { Any() }
            var indexSecond = 0
            for (valueSecond in second) {

                kotlintojdksecond[indexSecond] = valueSecond
                ++indexSecond
            }
            val result = jMergeString(kotlintojdkfirst, kotlintojdksecond, first, second)
            val jdktokotlinresult: MutableList<String> = mutableListOf()
            for (valueResult in result) {
                @Suppress("UNCHECKED_CAST") val actualValueresult = valueResult as String

                jdktokotlinresult.add(actualValueresult)
            }
            return jdktokotlinresult
        }
        @JvmStatic
        private external fun jMergeString(first: ObjectArray, second: ObjectArray, vararg extraObjs: Any?): ObjectArray
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::TemplateMethods"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    open fun max(a: Int, b: Int): Int {
        val result = jMaxInt(cppbindObjId, a, b)

        return result
    }

    open fun max(a: String, b: String): String {
        val result = jMaxString(cppbindObjId, a, b)

        return result
    }

    open fun makePair(a: Project, b: Project): Pair<Project, Project> {
        val kotlintojdka = a.cppbindObjId
        val kotlintojdkb = b.cppbindObjId
        val result = jMakepairProjectProject(cppbindObjId, kotlintojdka, kotlintojdkb, a, b)
        val firstResult = result.first
        val secondResult = result.second
        val jdktokotlinfirstResult = Project(CppBindObject(firstResult))
        val jdktokotlinsecondResult = Project(CppBindObject(secondResult))
        val jdktokotlinresult = Pair<Project, Project>(jdktokotlinfirstResult, jdktokotlinsecondResult)
        return jdktokotlinresult
    }

    open fun makePair(a: Root, b: Project): Pair<Root, Project> {
        val kotlintojdka = a.cppbindObjId
        val kotlintojdkb = b.cppbindObjId
        val result = jMakepairRootProject(cppbindObjId, kotlintojdka, kotlintojdkb, a, b)
        val firstResult = result.first
        val secondResult = result.second
        val jdktokotlinfirstResult = Root(CppBindObject(firstResult))
        val jdktokotlinsecondResult = Project(CppBindObject(secondResult))
        val jdktokotlinresult = Pair<Root, Project>(jdktokotlinfirstResult, jdktokotlinsecondResult)
        return jdktokotlinresult
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as TemplateMethods
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jMaxInt(id: Long, a: Int, b: Int, vararg extraObjs: Any?): Int
    private external fun jMaxString(id: Long, a: String, b: String, vararg extraObjs: Any?): String
    private external fun jMakepairProjectProject(id: Long, a: Long, b: Long, vararg extraObjs: Any?): Pair<Long, Long>
    private external fun jMakepairRootProject(id: Long, a: Long, b: Long, vararg extraObjs: Any?): Pair<Long, Long>
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 11/24/2022-07:17.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.templates.template_methods as pybind_template_methods_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *

if TYPE_CHECKING:
    import examples_lib.simple.project_pygen as simple_project_pygen
    import examples_lib.simple.root_pygen as simple_root_pygen


class TemplateMethods(metaclass=CppBindMetaclass):

    @bind
    def __init__(self):

        pass

    @bind
    def max(self, a: int, b: int) -> int:

        pass

    @bind
    def max(self, a: str, b: str) -> str:

        pass

    @bind
    def make_pair(self, a: simple_project_pygen.Project, b: simple_project_pygen.Project) -> Tuple[simple_project_pygen.Project, simple_project_pygen.Project]:

        pass

    @bind
    def make_pair(self, a: simple_root_pygen.Root, b: simple_project_pygen.Project) -> Tuple[simple_root_pygen.Root, simple_project_pygen.Project]:

        pass

    @classmethod
    @bind
    def merge(cls, first: List[int], second: List[int]) -> List[int]:

        pass

    @classmethod
    @bind
    def merge(cls, first: List[str], second: List[str]) -> List[str]:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/14/2022-10:59.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

public class TemplateMethods {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_TemplateMethods(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_TemplateMethods(&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")
      }
    }
  }

  public func max(a: Int, b: Int) -> Int {

    let swifttosca = CInt(a)
    let swifttoscb = CInt(b)
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_TemplateMethods_maxInt(cself, swifttosca, swifttoscb, &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
  }

  public func max(a: String, b: String) -> String {

    let swifttosca = strdup(a)!
    let swifttoscb = strdup(b)!
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_TemplateMethods_maxString(cself, swifttosca, swifttoscb, &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 = String(cString: result)
    defer {
      result.deallocate()
    }
    return sctoswiftresult
  }

  public func makePair(a: Project, b: Project) -> (Project, Project) {

    let swifttosca = a.cself
    let swifttoscb = b.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_TemplateMethods_makePairProjectProject(cself, swifttosca, swifttoscb, &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 _resultFirstData = UnsafeBufferPointer<CppBindCObject>(
      start: result.first.assumingMemoryBound(to: CppBindCObject.self),
      count: 1)
    let _resultSecondData = UnsafeBufferPointer<CppBindCObject>(
      start: result.second.assumingMemoryBound(to: CppBindCObject.self),
      count: 1)
    defer {
      _resultFirstData.deallocate()
      _resultSecondData.deallocate()
    }
    let resultFirst = _resultFirstData[0]
    let resultSecond = _resultSecondData[0]
    var sctoswiftresultFirst: Project
    sctoswiftresultFirst = Project(resultFirst)
    var sctoswiftresultSecond: Project
    sctoswiftresultSecond = Project(resultSecond)
    let sctoswiftresult: (Project, Project) = (sctoswiftresultFirst, sctoswiftresultSecond)
    return sctoswiftresult
  }

  public func makePair(a: Root, b: Project) -> (Root, Project) {

    let swifttosca = a.cself
    let swifttoscb = b.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_TemplateMethods_makePairRootProject(cself, swifttosca, swifttoscb, &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 _resultFirstData = UnsafeBufferPointer<CppBindCObject>(
      start: result.first.assumingMemoryBound(to: CppBindCObject.self),
      count: 1)
    let _resultSecondData = UnsafeBufferPointer<CppBindCObject>(
      start: result.second.assumingMemoryBound(to: CppBindCObject.self),
      count: 1)
    defer {
      _resultFirstData.deallocate()
      _resultSecondData.deallocate()
    }
    let resultFirst = _resultFirstData[0]
    let resultSecond = _resultSecondData[0]
    var sctoswiftresultFirst: Root
    sctoswiftresultFirst = Root(resultFirst)
    var sctoswiftresultSecond: Project
    sctoswiftresultSecond = Project(resultSecond)
    let sctoswiftresult: (Root, Project) = (sctoswiftresultFirst, sctoswiftresultSecond)
    return sctoswiftresult
  }

  public static func merge(first: Array<Int>, second: Array<Int>) -> Array<Int> {

    let _swifttoscfirstData = UnsafeMutablePointer<CInt>.allocate(capacity: first.count)
    var swifttoscfirst = CppBindCDataArray()
    swifttoscfirst.data = UnsafeMutableRawPointer(_swifttoscfirstData)
    swifttoscfirst.size = Int64(first.count)
    for i in 0..<first.count {
      let firstVal = first[i]
      let swifttoscfirstVal = CInt(firstVal)
      _swifttoscfirstData[i] = swifttoscfirstVal
    }
    let _swifttoscsecondData = UnsafeMutablePointer<CInt>.allocate(capacity: second.count)
    var swifttoscsecond = CppBindCDataArray()
    swifttoscsecond.data = UnsafeMutableRawPointer(_swifttoscsecondData)
    swifttoscsecond.size = Int64(second.count)
    for i in 0..<second.count {
      let secondVal = second[i]
      let swifttoscsecondVal = CInt(secondVal)
      _swifttoscsecondData[i] = swifttoscsecondVal
    }
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_TemplateMethods_mergeInt(swifttoscfirst, swifttoscsecond, &cppbindErr)

    swifttoscfirst.data.deallocate()

    swifttoscsecond.data.deallocate()
    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 _resultBuffer = UnsafeBufferPointer<CInt>(
      start: result.data.assumingMemoryBound(to: CInt.self),
      count: Int(result.size))
    var sctoswiftresult: [Int] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      let sctoswiftresultValue = Int(resultValue)
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  public static func merge(first: Array<String>, second: Array<String>) -> Array<String> {

    let _swifttoscfirstData = UnsafeMutablePointer<UnsafeMutablePointer<CChar>>.allocate(capacity: first.count)
    var swifttoscfirst = CppBindCDataArray()
    swifttoscfirst.data = UnsafeMutableRawPointer(_swifttoscfirstData)
    swifttoscfirst.size = Int64(first.count)
    for i in 0..<first.count {
      let firstVal = first[i]
      let swifttoscfirstVal = strdup(firstVal)!
      _swifttoscfirstData[i] = swifttoscfirstVal
    }
    let _swifttoscsecondData = UnsafeMutablePointer<UnsafeMutablePointer<CChar>>.allocate(capacity: second.count)
    var swifttoscsecond = CppBindCDataArray()
    swifttoscsecond.data = UnsafeMutableRawPointer(_swifttoscsecondData)
    swifttoscsecond.size = Int64(second.count)
    for i in 0..<second.count {
      let secondVal = second[i]
      let swifttoscsecondVal = strdup(secondVal)!
      _swifttoscsecondData[i] = swifttoscsecondVal
    }
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_TemplateMethods_mergeString(swifttoscfirst, swifttoscsecond, &cppbindErr)

    swifttoscfirst.data.deallocate()

    swifttoscsecond.data.deallocate()
    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 _resultBuffer = UnsafeBufferPointer<UnsafeMutablePointer<CChar>>(
      start: result.data.assumingMemoryBound(to: UnsafeMutablePointer<CChar>.self),
      count: Int(result.size))
    var sctoswiftresult: [String] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      let sctoswiftresultValue = String(cString: resultValue)
      defer {
        resultValue.deallocate()
      }
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::TemplateMethods" }
}

As we can see, CppBind generated two overloaded methods for each of the source methods. And here are some usage examples:

val tm = TemplateMethods()
val maxInt = tm.max(2, 5)
assert(maxInt == 5)
val maxString = tm.max("d", "a")
assert(maxString == "d")

val prj1 = Project("My first project")
val prj2 = Project("My second project")
var pairPrjPrj = tm.makePair(prj1, prj2)
assert(pairPrjPrj.first.title == prj1.title)
assert(pairPrjPrj.second.title == prj2.title)

val root1 = Root("/path/to/root/")
var pairRootPrj = tm.makePair(root1, prj1)
assert(pairRootPrj.first.path == root1.path)
assert(pairRootPrj.second.title == prj1.title)

val merged1 = TemplateMethods.merge(listOf(1, 2), listOf(3, 4))
assert(merged1 == listOf(1, 2, 3, 4))

val merged2 = TemplateMethods.merge(listOf("first", "second"), listOf("third"))
assert(merged2 == listOf("first", "second", "third"))
tm = TemplateMethods()
max_int = tm.max(a=2, b=5)
assert max_int == 5
max_string = tm.max(a="d", b="a")
assert max_string == "d"

prj1 = Project(title="My first project")
prj2 = Project(title="My second project")
pair_prj_prj = tm.make_pair(a=prj1, b=prj2)
assert len(pair_prj_prj) == 2
assert pair_prj_prj[0].title == prj1.title
assert pair_prj_prj[1].title == prj2.title

root1 = Root("/path/to/root/")
pair_root_prj = tm.make_pair(a=root1, b=prj1)
assert len(pair_root_prj) == 2
assert pair_root_prj[0].path == root1.path
assert pair_root_prj[1].title == prj1.title

merged1 = TemplateMethods.merge([1, 2], [3, 4])
assert merged1 == [1, 2, 3, 4]

merged2 = TemplateMethods.merge(["first", "second"], ["third"])
assert merged2 == ["first", "second", "third"]
let tm = TemplateMethods()
let maxInt = tm.max(a: 2, b: 5)
assert(maxInt == 5)
let maxString = tm.max(a: "d", b: "a")
assert(maxString == "d")

let prj1 = Project(title: "My first project")
let prj2 = Project(title: "My second project")
let pairPrjPrj = tm.makePair(a: prj1, b: prj2)
assert(Mirror(reflecting: pairPrjPrj).children.count == 2)
assert(pairPrjPrj.0.title == prj1.title)
assert(pairPrjPrj.1.title == prj2.title)

let root1 = Root(path: "/path/to/root/")
let pairRootPrj = tm.makePair(a: root1, b: prj1)
assert(Mirror(reflecting: pairRootPrj).children.count == 2)
assert(pairRootPrj.0.path == root1.path)
assert(pairRootPrj.1.title == prj1.title)

let merged1 = TemplateMethods.merge(first: [1, 2], second: [3, 4])
assert(merged1 == [1, 2, 3, 4])

let merged2 = TemplateMethods.merge(first: ["first", "second"], second: ["third"])
assert(merged2 == ["first", "second", "third"])

Note

In the case of Kotlin, the generated merge methods are also annotated with the JvmName annotation. Without this annotation, the two merge methods would have the same JVM signature, and the code would not compile. The annotation is generated if the is_kotlin_type_erased property from type converters' custom section is set to True for at least one of the arguments type converter. More on type converters can be found here

There might be cases when the exact instantiations must be specified. For these cases template_instance variable can be used. In the next section we'll see an examples using this variable.

Class templates

In this section we will see class template examples. Let's take a look at an example using template_instance variable:

/**
 * __API__
 * action: gen_class
 * package: templates
 * swift.file: template_vector
 * template_instance:
 *      - args: int, std::allocator<int>
 *        name: VectorInt
 *      - args: std::string, std::allocator<std::string>
 *        name: StringsVector
 *      - args: double, std::allocator<double>
 */
template <typename T, typename Allocator>
class Vector {

public:
    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    Vector() {}

    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    Vector(const cppbind::example::Vector<T, Allocator>& vec) : _vec(vec._vec) {}

    Vector(const std::vector<T>& vec) : _vec(vec) {}

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * swift.name: pushBack
     * kotlin.name: pushBack
     */
    void push_back(const T& value) {
        _vec.push_back(value);
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * swift.name: popBack
     * kotlin.name: popBack
     */
    void pop_back() {
        _vec.pop_back();
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    const T& operator[](int idx) const {
        return _vec[idx];
    }

    T& operator[](int idx) {
        return _vec[idx];
    }


    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    cppbind::example::Vector<T, Allocator> operator+(const cppbind::example::Vector<T, Allocator>& rhs) const {
        Vector res;
        for (int i = 0; i < _vec.size(); ++i) {
            res.push_back(_vec[i] + rhs[i]);
        }
        return res;
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    bool operator==(const cppbind::example::Vector<T, Allocator>& rhs) const {
        for (int i = 0; i < _vec.size(); ++i) {
            if (_vec[i] != rhs[i]) {
                return false;
            }
        }
        return true;
    }

private:
    std::vector<T, Allocator> _vec {};
};

Note

name key is handled differently for template and template_instance variables. In the case of template_instance it's the exact name of the generated type/function, while for the template it's used as a part of postfix for the generated type/function.

Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 10/11/2022-11:22.
 * Please do not change it manually.
 */

package com.examples.templates

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*

private val INIT = run {
    System.loadLibrary("wrapper_jni");
}

open class VectorInt
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long

        protected fun constructHelper(vec: VectorInt): Long {
            val kotlintojdkvec = vec.cppbindObjId
            val id = jConstructor1(kotlintojdkvec, vec)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(vec: Long, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Vector<int, std::allocator<int>>"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    constructor(vec: VectorInt): this(CppBindObject(constructHelper(vec), true)) {
    }

    fun pushBack(value: Int): Unit {
        val result = jPushback(cppbindObjId, value)

        return result
    }

    fun popBack(): Unit {
        val result = jPopback(cppbindObjId)

        return result
    }

    operator fun get(idx: Int): Int {
        val result = jGet(cppbindObjId, idx)

        return result
    }

    operator fun plus(rhs: VectorInt): VectorInt {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jPlus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = VectorInt(CppBindObject(result, true))
        return jdktokotlinresult
    }

    override fun equals(other: Any?): Boolean {
        other as VectorInt
        return jEquals(cppbindObjId, other.cppbindObjId, other)
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jPushback(id: Long, value: Int, vararg extraObjs: Any?): Unit
    private external fun jPopback(id: Long): Unit
    private external fun jGet(id: Long, idx: Int, vararg extraObjs: Any?): Int
    private external fun jPlus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jEquals(id: Long, rhs: Long, vararg extraObjs: Any?): Boolean
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

open class StringsVector
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long

        protected fun constructHelper(vec: StringsVector): Long {
            val kotlintojdkvec = vec.cppbindObjId
            val id = jConstructor1(kotlintojdkvec, vec)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(vec: Long, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Vector<std::string, std::allocator<std::string>>"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    constructor(vec: StringsVector): this(CppBindObject(constructHelper(vec), true)) {
    }

    fun pushBack(value: String): Unit {
        val result = jPushback(cppbindObjId, value)

        return result
    }

    fun popBack(): Unit {
        val result = jPopback(cppbindObjId)

        return result
    }

    operator fun get(idx: Int): String {
        val result = jGet(cppbindObjId, idx)

        return result
    }

    operator fun plus(rhs: StringsVector): StringsVector {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jPlus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = StringsVector(CppBindObject(result, true))
        return jdktokotlinresult
    }

    override fun equals(other: Any?): Boolean {
        other as StringsVector
        return jEquals(cppbindObjId, other.cppbindObjId, other)
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jPushback(id: Long, value: String, vararg extraObjs: Any?): Unit
    private external fun jPopback(id: Long): Unit
    private external fun jGet(id: Long, idx: Int, vararg extraObjs: Any?): String
    private external fun jPlus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jEquals(id: Long, rhs: Long, vararg extraObjs: Any?): Boolean
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

open class Vector
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long

        protected fun constructHelper(vec: Vector): Long {
            val kotlintojdkvec = vec.cppbindObjId
            val id = jConstructor1(kotlintojdkvec, vec)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(vec: Long, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Vector<double, std::allocator<double>>"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    constructor(vec: Vector): this(CppBindObject(constructHelper(vec), true)) {
    }

    fun pushBack(value: Double): Unit {
        val result = jPushback(cppbindObjId, value)

        return result
    }

    fun popBack(): Unit {
        val result = jPopback(cppbindObjId)

        return result
    }

    operator fun get(idx: Int): Double {
        val result = jGet(cppbindObjId, idx)

        return result
    }

    operator fun plus(rhs: Vector): Vector {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jPlus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = Vector(CppBindObject(result, true))
        return jdktokotlinresult
    }

    override fun equals(other: Any?): Boolean {
        other as Vector
        return jEquals(cppbindObjId, other.cppbindObjId, other)
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jPushback(id: Long, value: Double, vararg extraObjs: Any?): Unit
    private external fun jPopback(id: Long): Unit
    private external fun jGet(id: Long, idx: Int, vararg extraObjs: Any?): Double
    private external fun jPlus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jEquals(id: Long, rhs: Long, vararg extraObjs: Any?): Boolean
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

/**
 * An example with variadic template.
 */
fun createVector(args1: Int, args2: Int): VectorInt {
    val result = jCreatevectorIntIntInt(args1, args2)
    val jdktokotlinresult = VectorInt(CppBindObject(result, true))
    return jdktokotlinresult
}

private external fun jCreatevectorIntIntInt(args1: Int, args2: Int, vararg extraObjs: Any?): Long

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 10/12/2022-06:55.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.templates.vector as pybind_vector_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *


class VectorInt(metaclass=CppBindMetaclass):

    @bind
    def __init__(self):

        pass

    @bind
    def __init__(self, vec: VectorInt):

        pass

    @bind
    def push_back(self, value: int) -> None:

        pass

    @bind
    def pop_back(self) -> None:

        pass

    @bind
    def __getitem__(self, idx: int) -> int:

        pass

    @bind
    def __add__(self, rhs: VectorInt) -> VectorInt:

        pass

    @bind
    def __eq__(self, rhs: VectorInt) -> bool:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class StringsVector(metaclass=CppBindMetaclass):

    @bind
    def __init__(self):

        pass

    @bind
    def __init__(self, vec: StringsVector):

        pass

    @bind
    def push_back(self, value: str) -> None:

        pass

    @bind
    def pop_back(self) -> None:

        pass

    @bind
    def __getitem__(self, idx: int) -> str:

        pass

    @bind
    def __add__(self, rhs: StringsVector) -> StringsVector:

        pass

    @bind
    def __eq__(self, rhs: StringsVector) -> bool:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class Vector(metaclass=CppBindMetaclass):

    @bind
    def __init__(self):

        pass

    @bind
    def __init__(self, vec: Vector):

        pass

    @bind
    def push_back(self, value: float) -> None:

        pass

    @bind
    def pop_back(self) -> None:

        pass

    @bind
    def __getitem__(self, idx: int) -> float:

        pass

    @bind
    def __add__(self, rhs: Vector) -> Vector:

        pass

    @bind
    def __eq__(self, rhs: Vector) -> bool:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


@bind
def create_vector_int_int_int(args1: int, args2: int) -> VectorInt:
    """
    An example with variadic template.
    """
    pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 10/12/2022-07:52.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

public class VectorInt {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_VectorInt(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_VectorInt(&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")
      }
    }
  }

  public convenience init(vec: VectorInt) {
    let swifttoscvec = vec.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_VectorInt1(swifttoscvec, &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")
      }
    }
  }

  public func pushBack(value: Int) -> Void {

    let swifttoscvalue = CInt(value)
    var cppbindErr = CppBindCObject()
    _func_CppbindExample_VectorInt_pushBack(cself, swifttoscvalue, &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")
      }
    }
  }

  public func popBack() -> Void {

    var cppbindErr = CppBindCObject()
    _func_CppbindExample_VectorInt_popBack(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")
      }
    }
  }



  public subscript(idx: Int) -> Int {
    let swifttoscidx = CInt(idx)
    let result = _func_CppbindExample_VectorInt__getitem_(cself, swifttoscidx)
    let sctoswiftresult = Int(result)
    return sctoswiftresult
  }

  public static func +(cself: VectorInt, rhs: VectorInt) -> VectorInt {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_VectorInt__add_(cself.cself, swifttoscrhs, &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: VectorInt
    sctoswiftresult = VectorInt(result, true)
    return sctoswiftresult
  }

  public static func ==(cself: VectorInt, rhs: VectorInt) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_VectorInt__eq_(cself.cself, swifttoscrhs, &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
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Vector<int, std::allocator<int>>" }
}

public class StringsVector {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_StringsVector(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StringsVector(&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")
      }
    }
  }

  public convenience init(vec: StringsVector) {
    let swifttoscvec = vec.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StringsVector1(swifttoscvec, &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")
      }
    }
  }

  public func pushBack(value: String) -> Void {

    let swifttoscvalue = strdup(value)!
    var cppbindErr = CppBindCObject()
    _func_CppbindExample_StringsVector_pushBack(cself, swifttoscvalue, &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")
      }
    }
  }

  public func popBack() -> Void {

    var cppbindErr = CppBindCObject()
    _func_CppbindExample_StringsVector_popBack(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")
      }
    }
  }



  public subscript(idx: Int) -> String {
    let swifttoscidx = CInt(idx)
    let result = _func_CppbindExample_StringsVector__getitem_(cself, swifttoscidx)
    let sctoswiftresult = String(cString: result)
      defer {
        result.deallocate()
      }
    return sctoswiftresult
  }

  public static func +(cself: StringsVector, rhs: StringsVector) -> StringsVector {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_StringsVector__add_(cself.cself, swifttoscrhs, &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: StringsVector
    sctoswiftresult = StringsVector(result, true)
    return sctoswiftresult
  }

  public static func ==(cself: StringsVector, rhs: StringsVector) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_StringsVector__eq_(cself.cself, swifttoscrhs, &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
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Vector<std::string, std::allocator<std::string>>" }
}

public class Vector {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_Vector(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Vector(&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")
      }
    }
  }

  public convenience init(vec: Vector) {
    let swifttoscvec = vec.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Vector1(swifttoscvec, &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")
      }
    }
  }

  public func pushBack(value: Double) -> Void {

    var cppbindErr = CppBindCObject()
    _func_CppbindExample_Vector_pushBack(cself, value, &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")
      }
    }
  }

  public func popBack() -> Void {

    var cppbindErr = CppBindCObject()
    _func_CppbindExample_Vector_popBack(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")
      }
    }
  }



  public subscript(idx: Int) -> Double {
    let swifttoscidx = CInt(idx)
    let result = _func_CppbindExample_Vector__getitem_(cself, swifttoscidx)
    return result
  }

  public static func +(cself: Vector, rhs: Vector) -> Vector {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Vector__add_(cself.cself, swifttoscrhs, &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: Vector
    sctoswiftresult = Vector(result, true)
    return sctoswiftresult
  }

  public static func ==(cself: Vector, rhs: Vector) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Vector__eq_(cself.cself, swifttoscrhs, &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
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Vector<double, std::allocator<double>>" }
}

/// An example with variadic template.
public func createVector(args1: Int, args2: Int) -> VectorInt {
  let swifttoscargs1 = CInt(args1)
  let swifttoscargs2 = CInt(args2)
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_createVectorIntIntInt(swifttoscargs1, swifttoscargs2, &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: VectorInt
  sctoswiftresult = VectorInt(result, true)
  return sctoswiftresult
}

For a class template, CppBind generates a new type for each instantiation. Here we have three generated types: VectorInt, Vector and StringsVector.

And here are the usage examples:

val vecInt = VectorInt()
vecInt.pushBack(1)
assert(vecInt[0] == 1)
val vecIntCopy = VectorInt(vecInt)
assert(vecInt == vecIntCopy)
val vecIntSum = vecInt + vecIntCopy
assert(vecIntSum[0] == 2)

val vecString = StringsVector()
vecString.pushBack("a")
assert(vecString[0] == "a")
val vecStringCopy = StringsVector(vecString)
assert(vecString == vecStringCopy)
val vecStringSum = vecString + vecStringCopy
assert(vecStringSum[0] == "aa")

val vecDouble = Vector()
vecDouble.pushBack(1.0)
assert(vecDouble[0] == 1.0)
val vecDoubleCopy = Vector(vecDouble)
assert(vecDouble == vecDoubleCopy)
val vecDoubleSum = vecDouble + vecDoubleCopy
assert(vecDoubleSum[0] == 2.0)
vec_int = VectorInt()
vec_int.push_back(1)
assert vec_int[0] == 1
vec_int_copy = VectorInt(vec_int)
assert vec_int == vec_int_copy
vec_int_sum = vec_int + vec_int_copy
assert vec_int_sum[0] == 2

vec_string = StringsVector()
vec_string.push_back("a")
assert vec_string[0] == "a"
vec_string_copy = StringsVector(vec_string)
assert vec_string == vec_string_copy
vec_string_sum = vec_string + vec_string_copy
assert vec_string_sum[0] == "aa"

vec_double = Vector()
vec_double.push_back(1.0)
assert vec_double[0] == 1.0
vec_double_copy = Vector(vec_double)
assert vec_double == vec_double_copy
vec_double_sum = vec_double + vec_double_copy
assert vec_double_sum[0] == 2.0
let vecInt = VectorInt()
vecInt.pushBack(value: 1)
assert(vecInt[0] == 1)
let vecIntCopy = VectorInt(vec: vecInt)
assert(vecInt == vecIntCopy)
let vecIntSum = vecInt + vecIntCopy
assert(vecIntSum[0] == 2)

let vecString = StringsVector()
vecString.pushBack(value: "a")
assert(vecString[0] == "a")
let vecStringCopy = StringsVector(vec: vecString)
assert(vecString == vecStringCopy)
let vecStringSum = vecString + vecStringCopy
assert(vecStringSum[0] == "aa")

let vecDouble = Vector()
vecDouble.pushBack(value: 1.0)
assert(vecDouble[0] == 1.0)
let vecDoubleCopy = Vector(vec: vecDouble)
assert(vecDouble == vecDoubleCopy)
let vecDoubleSum = vecDouble + vecDoubleCopy
assert(vecDoubleSum[0] == 2.0)

Now let's see another example using template variable. In this example we have a template class Stack<T> and we've specified values that parameter T can have.

Here is the code in C++:

  /**
   * An example of a class template.
   * __API__
   * action: gen_class
   * template:
   *   T:
   *     - type: cppbind::example::Project
   *       name: Prj
   *     - type: cppbind::example::Task
   *     - type: cppbind::example::Number<int>
   *       name: NumInt
   * package: templates
   */
  template <class T>
  class Stack: public Container {

  public:
      /**
       * __API__
       * action: gen_constructor
       * throws: no_throw
       */
      Stack() {};

      /**
       * Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
       * cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
       * enough information.
       * __API__
       * action: gen_constructor
       * throws: no_throw
       */
      Stack(cppbind::example::Stack<T>& stack) : _elements(stack._elements) {};

      /**
       * __API__
       * action: gen_constructor
       * throws: no_throw
       */
      Stack(T* st) {
          push(st);
      };

      /**
       * __API__
       * action: gen_method
       * throws: no_throw
       */
      void push(T* item) {
          _elements.push_back(item);
      };

      /**
       * __API__
       * action: gen_method
       * throws: no_throw
       */
      void pop() {
          _elements.pop_back();
      };

      /**
       * __API__
       * action: gen_method
       * throws: no_throw
       * return_value_policy: reference
       */
      T* top() const {
          return _elements.back();
      };

       /**
        * __API__
        * action: gen_method
        * throws: no_throw
        */
      bool empty() const {
           return _elements.empty();
      }

  private:
      std::vector<T*> _elements;

  };


  template <>
  class Stack<cppbind::example::Project>: public Container {

  public:

      Stack() {};

      Stack(cppbind::example::Stack<cppbind::example::Project>& stack) : _elements(stack._elements) {};

      Stack(cppbind::example::Project* st) {
          push(st);
      };

      void push(cppbind::example::Project* item) {
          _elements.push_back(item);
      };

      void pop() {
          _elements.pop_back();
      };

      cppbind::example::Project* top() const {
          return _elements.back();
      };

      bool empty() const {
           return _elements.empty();
      }

  private:
      std::vector<cppbind::example::Project*> _elements;

  };

We specified three values for template parameter T which means three instantiations of Stack will be exposed to target languages: cppbind::example::Stack<cppbind::example::Task>, cppbind::example::Stack<cppbind::example::Project>, cppbind::example::Stack<cppbind::example::Number<int>>. CppBind will generate a new class for each of these specializations.

Note that we have specified name property for cppbind::example::Project and cppbind::example::Number<int>. This property is used as a type name postfix in target language, i.e. StackPrj will be generated for cppbind::example::Stack<cppbind::example::Project> and StackNumInt for cppbind::example::Stack<cppbind::example::Number<int>>. For cppbind::example::Task we have not specified the property name, which means StackTask will be generated. In this case tname property from type converter's custom section is used as a postfix. More on type converters can be found here.

var stackPrj = StackPrj()
assert(stackPrj.empty())
val prj = Project("My Project")
stackPrj.push(prj)
assert(!stackPrj.empty())
assert(stackPrj.top().title == prj.title)
stackPrj.pop()
assert(stackPrj.empty())

val stackNumber = StackNumInt()
val num1 = NumberInt(1)
val num2 = NumberInt(2)
stackNumber.push(num1)
stackNumber.push(num2)
assert(stackNumber.top().num == num2.num)
stackNumber.pop()
assert(stackNumber.top().num == num1.num)

stackPrj.push(prj)
val stackPrjCopy = StackPrj(stackPrj)
assert(stackPrj.top() == stackPrjCopy.top())

// specialized stack usage
val stackRoot = RootsStack()
val rootHome = Root("/home")
stackRoot.push(rootHome)
assert(stackRoot.top().path == rootHome.path)
stack_prj = StackPrj()
assert stack_prj.empty()
prj = Project(title="My Project")
stack_prj.push(item=prj)
assert stack_prj.empty() is False
assert stack_prj.top().title == prj.title
stack_prj.pop()
assert stack_prj.empty() is True

stackNumber = StackNumInt()
num1 = NumberInt(1)
num2 = NumberInt(2)
stackNumber.push(num1)
stackNumber.push(num2)
assert stackNumber.top().num == num2.num
stackNumber.pop()
assert stackNumber.top().num == num1.num

stack_prj.push(prj)
stack_prj_copy = StackPrj(stack_prj)
assert stack_prj.top() == stack_prj_copy.top()
let stackPrj = StackPrj()
assert(stackPrj.empty())
let prj = Project(title: "My Project")
stackPrj.push(item: prj)
assert(!stackPrj.empty())
assert(stackPrj.top().title == prj.title)
stackPrj.pop()
assert(stackPrj.empty())

let stackNumber = StackNumInt()
let num1 = NumberInt(n: 1)
let num2 = NumberInt(n: 2)
stackNumber.push(item: num1)
stackNumber.push(item: num2)
assert(stackNumber.top().num == num2.num)
stackNumber.pop()
assert(stackNumber.top().num == num1.num)

stackPrj.push(item: prj)
let stackPrjCopy = StackPrj(stack: stackPrj)
assert(stackPrj.top() == stackPrjCopy.top())

// specialized stack usage
let stackRoot = RootsStack()
let rootHome = Root(path: "/home")
stackRoot.push(item: rootHome)
assert(stackRoot.top().path == rootHome.path)

Now let's see how CppBind handles cases when the Stack template class is used as a function argument.

  /**
   * __API__
   * action: gen_class
   * package: templates
   */
  class StackUsage  {
      public:
      /**
       * __API__
       * action: gen_constructor
       * throws: no_throw
       */
      StackUsage() {};

      /**
       * __API__
       * action: gen_method
       * throws: no_throw
       * return_value_policy: reference
       */
      Project* firstItemOfSpecializedStack(Stack<Project>* p) {
          return p->top();
      };

      using StackProject = Stack<Project>;

      /**
       * __API__
       * action: gen_method
       * throws: no_throw
       * return_value_policy: reference
       */
      Project* firstItemOfTypedefOfSpecializedStack(StackProject* p) {
          return p->top();
      };

      /**
       * Full type name(i.e., cppbind::example::Stack<V> not just Stack<V>) should be explicitly specified otherwise
       * cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
       * enough information.
       * __API__
       * action: gen_method
       * template:
       *   V:
       *     - type: cppbind::example::Project
       * throws: no_throw
       * return_value_policy: reference
       */
      template <typename V>
      V* firstItemOfTemplateStack(cppbind::example::Stack<V>* p) {
          return p->top();
      };

      /**
       * Example to check typedef argument types
       * __API__
       * action: gen_method
       * throws: no_throw
       * return_value_policy: reference
       */
      Project* firstItemOfSpecializedStackWithTypedefArg(StackProjectType* p) {
          return p->top();
      };

      // not supported use cases

      /**
       * Templates without full type names are not supported. Argument full type name(cppbind::example::Stack<V>) should
       * be explicitly specified, so that cppbind can parse the argument.
       */
      template <typename V>
      V* firstItemOfTemplateStackNotSupported(Stack<V>* p) {
          return p->top();
      };

  };

Here we have five methods to take Stack as an argument and return its first element. CppBind supports the first four methods, but you cannot generate bindings for the fifth. To generate bindings for a function taking template arguments, you must specify their full type names. The fifth one does not meet this requirement.

Note

CppBind supports types inherited from a specialized template, e.g., class TaskList: public Stack<Task>. And to generate bindings for a type inherited from a template type (has CppBind API), you must specify full name of the base type, e.g., class TaskList<T>: public cppbind::example::Stack<T>.

libclang does not provide enough information on template types and these requirements are added to take the missing information from user provided APIs.

Note

Due to this missing information, currently CppBind does not support typedefs on template types, even if the type name is fully specified, e.g., using Stack = cppbind::example::Stack<T> is not supported.

Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 11/10/2022-06:59.
 * Please do not change it manually.
 */

package com.examples.templates

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*
import com.examples.getters.NumberInt
import com.examples.simple.Project
import com.examples.simple.task.Task

/**
 * An example of a class template.
 */
open class StackPrj
internal constructor(obj: CppBindObject) : IContainer, AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long

        /**
         * Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
         * cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
         * enough information.
         */
        protected fun constructHelper(stack: StackPrj): Long {
            val kotlintojdkstack = stack.cppbindObjId
            val id = jConstructor1(kotlintojdkstack, stack)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(stack: Long, vararg extraObjs: Any?): Long

        protected fun constructHelper(st: Project): Long {
            val kotlintojdkst = st.cppbindObjId
            val id = jConstructor2(kotlintojdkst, st)
            return id
        }

        @JvmStatic
        private external fun jConstructor2(st: Long, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Stack<cppbind::example::Project>"

        /**
         * An internal method to create a Kotlin object from a C++ object.
         * It is intended to be used by the generated code.
         */
        public fun cppbindConstructObject(id: Long, owner: Boolean = false): StackPrj {
            val idType = jGettypebyid(id)
            val obj : Any
            when (idType) {
                MyStackProject.cppbindCxxTypeName -> obj = MyStackProject(CppBindObject(id, owner))
                MyStackTask.cppbindCxxTypeName -> obj = MyStackTask(CppBindObject(id, owner))
                else -> obj = StackPrj(CppBindObject(id, owner))
            }
            return obj as StackPrj
        }
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    override fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    override val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    /**
     * Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
     * cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
     * enough information.
     */
    constructor(stack: StackPrj): this(CppBindObject(constructHelper(stack), true)) {
    }

    constructor(st: Project): this(CppBindObject(constructHelper(st), true)) {
    }

    fun push(item: Project): Unit {
        val kotlintojdkitem = item.cppbindObjId
        val result = jPush(cppbindObjId, kotlintojdkitem, item)

        return result
    }

    fun pop(): Unit {
        val result = jPop(cppbindObjId)

        return result
    }

    fun top(): Project {
        val result = jTop(cppbindObjId)
        val jdktokotlinresult = Project(CppBindObject(result))
        return jdktokotlinresult
    }

    fun empty(): Boolean {
        val result = jEmpty(cppbindObjId)

        return result
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as StackPrj
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jPush(id: Long, item: Long, vararg extraObjs: Any?): Unit
    private external fun jPop(id: Long): Unit
    private external fun jTop(id: Long): Long
    private external fun jEmpty(id: Long): Boolean
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

/**
 * An example of a class template.
 */
open class StackTask
internal constructor(obj: CppBindObject) : IContainer, AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long

        /**
         * Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
         * cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
         * enough information.
         */
        protected fun constructHelper(stack: StackTask): Long {
            val kotlintojdkstack = stack.cppbindObjId
            val id = jConstructor1(kotlintojdkstack, stack)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(stack: Long, vararg extraObjs: Any?): Long

        protected fun constructHelper(st: Task): Long {
            val kotlintojdkst = st.cppbindObjId
            val id = jConstructor2(kotlintojdkst, st)
            return id
        }

        @JvmStatic
        private external fun jConstructor2(st: Long, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Stack<cppbind::example::Task>"

        /**
         * An internal method to create a Kotlin object from a C++ object.
         * It is intended to be used by the generated code.
         */
        public fun cppbindConstructObject(id: Long, owner: Boolean = false): StackTask {
            val idType = jGettypebyid(id)
            val obj : Any
            when (idType) {
                MyStackProject.cppbindCxxTypeName -> obj = MyStackProject(CppBindObject(id, owner))
                MyStackTask.cppbindCxxTypeName -> obj = MyStackTask(CppBindObject(id, owner))
                else -> obj = StackTask(CppBindObject(id, owner))
            }
            return obj as StackTask
        }
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    override fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    override val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    /**
     * Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
     * cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
     * enough information.
     */
    constructor(stack: StackTask): this(CppBindObject(constructHelper(stack), true)) {
    }

    constructor(st: Task): this(CppBindObject(constructHelper(st), true)) {
    }

    fun push(item: Task): Unit {
        val kotlintojdkitem = item.cppbindObjId
        val result = jPush(cppbindObjId, kotlintojdkitem, item)

        return result
    }

    fun pop(): Unit {
        val result = jPop(cppbindObjId)

        return result
    }

    fun top(): Task {
        val result = jTop(cppbindObjId)
        val jdktokotlinresult = Task(CppBindObject(result))
        return jdktokotlinresult
    }

    fun empty(): Boolean {
        val result = jEmpty(cppbindObjId)

        return result
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as StackTask
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jPush(id: Long, item: Long, vararg extraObjs: Any?): Unit
    private external fun jPop(id: Long): Unit
    private external fun jTop(id: Long): Long
    private external fun jEmpty(id: Long): Boolean
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

/**
 * An example of a class template.
 */
open class StackNumInt
internal constructor(obj: CppBindObject) : IContainer, AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long

        /**
         * Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
         * cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
         * enough information.
         */
        protected fun constructHelper(stack: StackNumInt): Long {
            val kotlintojdkstack = stack.cppbindObjId
            val id = jConstructor1(kotlintojdkstack, stack)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(stack: Long, vararg extraObjs: Any?): Long

        protected fun constructHelper(st: NumberInt): Long {
            val kotlintojdkst = st.cppbindObjId
            val id = jConstructor2(kotlintojdkst, st)
            return id
        }

        @JvmStatic
        private external fun jConstructor2(st: Long, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Stack<cppbind::example::Number<int>>"

        /**
         * An internal method to create a Kotlin object from a C++ object.
         * It is intended to be used by the generated code.
         */
        public fun cppbindConstructObject(id: Long, owner: Boolean = false): StackNumInt {
            val idType = jGettypebyid(id)
            val obj : Any
            when (idType) {
                MyStackProject.cppbindCxxTypeName -> obj = MyStackProject(CppBindObject(id, owner))
                MyStackTask.cppbindCxxTypeName -> obj = MyStackTask(CppBindObject(id, owner))
                else -> obj = StackNumInt(CppBindObject(id, owner))
            }
            return obj as StackNumInt
        }
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    override fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    override val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    /**
     * Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
     * cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
     * enough information.
     */
    constructor(stack: StackNumInt): this(CppBindObject(constructHelper(stack), true)) {
    }

    constructor(st: NumberInt): this(CppBindObject(constructHelper(st), true)) {
    }

    fun push(item: NumberInt): Unit {
        val kotlintojdkitem = item.cppbindObjId
        val result = jPush(cppbindObjId, kotlintojdkitem, item)

        return result
    }

    fun pop(): Unit {
        val result = jPop(cppbindObjId)

        return result
    }

    fun top(): NumberInt {
        val result = jTop(cppbindObjId)
        val jdktokotlinresult = NumberInt(CppBindObject(result))
        return jdktokotlinresult
    }

    fun empty(): Boolean {
        val result = jEmpty(cppbindObjId)

        return result
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as StackNumInt
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jPush(id: Long, item: Long, vararg extraObjs: Any?): Unit
    private external fun jPop(id: Long): Unit
    private external fun jTop(id: Long): Long
    private external fun jEmpty(id: Long): Boolean
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 11/24/2022-07:17.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.templates.stack as pybind_stack_pygen
import examples_lib.templates.container_pygen as container_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *

if TYPE_CHECKING:
    import examples_lib.getters.number_pygen as getters_number_pygen
    import examples_lib.simple.project_pygen as simple_project_pygen
    import examples_lib.simple.task.task_pygen as simple_task_task_pygen


class StackPrj(container_pygen.Container, metaclass=CppBindMetaclass):
    """
    An example of a class template.
    """

    @bind
    def __init__(self):

        pass

    @bind
    def __init__(self, stack: StackPrj):
        """
        Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
        cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
        enough information.
        """
        pass

    @bind
    def __init__(self, st: simple_project_pygen.Project):

        pass

    @bind
    def push(self, item: simple_project_pygen.Project) -> None:

        pass

    @bind
    def pop(self) -> None:

        pass

    @bind
    def top(self) -> simple_project_pygen.Project:

        pass

    @bind
    def empty(self) -> bool:

        pass


class StackPyTask(container_pygen.Container, metaclass=CppBindMetaclass):
    """
    An example of a class template.
    """

    @bind
    def __init__(self):

        pass

    @bind
    def __init__(self, stack: StackPyTask):
        """
        Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
        cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
        enough information.
        """
        pass

    @bind
    def __init__(self, st: simple_task_task_pygen.PyTask):

        pass

    @bind
    def push(self, item: simple_task_task_pygen.PyTask) -> None:

        pass

    @bind
    def pop(self) -> None:

        pass

    @bind
    def top(self) -> simple_task_task_pygen.PyTask:

        pass

    @bind
    def empty(self) -> bool:

        pass


class StackNumInt(container_pygen.Container, metaclass=CppBindMetaclass):
    """
    An example of a class template.
    """

    @bind
    def __init__(self):

        pass

    @bind
    def __init__(self, stack: StackNumInt):
        """
        Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
        cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
        enough information.
        """
        pass

    @bind
    def __init__(self, st: getters_number_pygen.NumberInt):

        pass

    @bind
    def push(self, item: getters_number_pygen.NumberInt) -> None:

        pass

    @bind
    def pop(self) -> None:

        pass

    @bind
    def top(self) -> getters_number_pygen.NumberInt:

        pass

    @bind
    def empty(self) -> bool:

        pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 10/13/2022-12:53.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

/// An example of a class template.
public class StackPrj: Container {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_StackPrj(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  /// internal dummy initializer to prevent automatic initializer inheritance
  internal init(_cself: CppBindCObject, _self: StackPrj) {
    fatalError("A dummy internal initializer should not be called.")
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StackPrj(&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")
      }
    }
  }

  /// Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
  /// cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
  /// enough information.
  public convenience init(stack: StackPrj) {
    let swifttoscstack = stack.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StackPrj1(swifttoscstack, &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")
      }
    }
  }

  public convenience init(st: Project) {
    let swifttoscst = st.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StackPrj2(swifttoscst, &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")
      }
    }
  }

  public func push(item: Project) -> Void {

    let swifttoscitem = item.cself
    var cppbindErr = CppBindCObject()
    _func_CppbindExample_StackPrj_push(cself, swifttoscitem, &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")
      }
    }
  }

  public func pop() -> Void {

    var cppbindErr = CppBindCObject()
    _func_CppbindExample_StackPrj_pop(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")
      }
    }
  }

  public func top() -> Project {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_StackPrj_top(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")
      }
    }
    var sctoswiftresult: Project
    sctoswiftresult = Project(result)
    return sctoswiftresult
  }

  public func empty() -> Bool {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_StackPrj_empty(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")
      }
    }
    return result
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Stack<cppbind::example::Project>" }

  /// An internal method to create a Swift object from a C++ object.
  /// It is intended to be used by the generated code.
  class func cppbindConstructObject(_ cppbindObj: CppBindCObject, _ owner: Bool = false) -> StackPrj {
    let typeName = String(cString: cppbindObj.type)
    var obj : Any
    switch(typeName) {
    case(MyStackProject.cppbindCxxTypeName):
      obj = MyStackProject(cppbindObj, owner)
    case(MyStackTask.cppbindCxxTypeName):
      obj = MyStackTask(cppbindObj, owner)
    default:
      obj = StackPrj(cppbindObj, owner)
    }
    return obj as! StackPrj
  }
}

/// An example of a class template.
public class StackTask: Container {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_StackTask(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  /// internal dummy initializer to prevent automatic initializer inheritance
  internal init(_cself: CppBindCObject, _self: StackTask) {
    fatalError("A dummy internal initializer should not be called.")
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StackTask(&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")
      }
    }
  }

  /// Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
  /// cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
  /// enough information.
  public convenience init(stack: StackTask) {
    let swifttoscstack = stack.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StackTask1(swifttoscstack, &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")
      }
    }
  }

  public convenience init(st: Task) {
    let swifttoscst = st.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StackTask2(swifttoscst, &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")
      }
    }
  }

  public func push(item: Task) -> Void {

    let swifttoscitem = item.cself
    var cppbindErr = CppBindCObject()
    _func_CppbindExample_StackTask_push(cself, swifttoscitem, &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")
      }
    }
  }

  public func pop() -> Void {

    var cppbindErr = CppBindCObject()
    _func_CppbindExample_StackTask_pop(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")
      }
    }
  }

  public func top() -> Task {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_StackTask_top(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")
      }
    }
    var sctoswiftresult: Task
    sctoswiftresult = Task(result)
    return sctoswiftresult
  }

  public func empty() -> Bool {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_StackTask_empty(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")
      }
    }
    return result
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Stack<cppbind::example::Task>" }

  /// An internal method to create a Swift object from a C++ object.
  /// It is intended to be used by the generated code.
  class func cppbindConstructObject(_ cppbindObj: CppBindCObject, _ owner: Bool = false) -> StackTask {
    let typeName = String(cString: cppbindObj.type)
    var obj : Any
    switch(typeName) {
    case(MyStackProject.cppbindCxxTypeName):
      obj = MyStackProject(cppbindObj, owner)
    case(MyStackTask.cppbindCxxTypeName):
      obj = MyStackTask(cppbindObj, owner)
    default:
      obj = StackTask(cppbindObj, owner)
    }
    return obj as! StackTask
  }
}

/// An example of a class template.
public class StackNumInt: Container {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_StackNumInt(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  /// internal dummy initializer to prevent automatic initializer inheritance
  internal init(_cself: CppBindCObject, _self: StackNumInt) {
    fatalError("A dummy internal initializer should not be called.")
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StackNumInt(&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")
      }
    }
  }

  /// Full type name(i.e., cppbind::example::Stack<T> not just Stack<T>) should be explicitly specified otherwise
  /// cppbind won't be able to generate a converter for the argument, as for templates libclang does not provide
  /// enough information.
  public convenience init(stack: StackNumInt) {
    let swifttoscstack = stack.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StackNumInt1(swifttoscstack, &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")
      }
    }
  }

  public convenience init(st: NumberInt) {
    let swifttoscst = st.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_StackNumInt2(swifttoscst, &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")
      }
    }
  }

  public func push(item: NumberInt) -> Void {

    let swifttoscitem = item.cself
    var cppbindErr = CppBindCObject()
    _func_CppbindExample_StackNumInt_push(cself, swifttoscitem, &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")
      }
    }
  }

  public func pop() -> Void {

    var cppbindErr = CppBindCObject()
    _func_CppbindExample_StackNumInt_pop(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")
      }
    }
  }

  public func top() -> NumberInt {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_StackNumInt_top(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")
      }
    }
    var sctoswiftresult: NumberInt
    sctoswiftresult = NumberInt(result)
    return sctoswiftresult
  }

  public func empty() -> Bool {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_StackNumInt_empty(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")
      }
    }
    return result
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Stack<cppbind::example::Number<int>>" }

  /// An internal method to create a Swift object from a C++ object.
  /// It is intended to be used by the generated code.
  class func cppbindConstructObject(_ cppbindObj: CppBindCObject, _ owner: Bool = false) -> StackNumInt {
    let typeName = String(cString: cppbindObj.type)
    var obj : Any
    switch(typeName) {
    case(MyStackProject.cppbindCxxTypeName):
      obj = MyStackProject(cppbindObj, owner)
    case(MyStackTask.cppbindCxxTypeName):
      obj = MyStackTask(cppbindObj, owner)
    default:
      obj = StackNumInt(cppbindObj, owner)
    }
    return obj as! StackNumInt
  }
}

Template Getters/Setters

Now let's see how the name is used for template getters/setters.

/**
 * __API__
 * action: gen_enum
 * package: getters
 */
enum class FruitType {
    Apple = 1,
    Pineapple = 2,
};


/**
 * __API__
 * action: gen_class
 * package: getters
 */
struct Fruit  {

    Fruit() {};

    /**
     * __API__
     * action: gen_getter
     * throws: no_throw
     */
    virtual FruitType type() const = 0;

    virtual ~Fruit() = default;
};


/**
 * __API__
 * action: gen_class
 * package: getters
 */
struct Apple : public Fruit  {

    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    Apple() : Fruit() {};

    /**
     * __API__
     * action: gen_getter
     * throws: no_throw
     */
    FruitType type() const override {
        return FruitType::Apple;
    }

    static const FruitType Type = FruitType::Apple;
};

/**
 * __API__
 * action: gen_class
 * package: getters
 */
struct Pineapple : public Fruit  {

    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    Pineapple() : Fruit() {};

    /**
     * __API__
     * action: gen_getter
     * throws: no_throw
     */
    FruitType type() const override {
        return FruitType::Pineapple;
    }
    static const FruitType Type = FruitType::Pineapple;

};

/**
 * An example class containing template getters.
 * __API__
 * action: gen_class
 * package: getters
 */
class Fruits  {
    public:
    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    Fruits(const std::vector<Fruit*>& fruits) : _fruits(fruits) {};

    /**
     * __API__
     * action: gen_getter
     * throws: no_throw
     * template:
     *   T:
     *     - type: cppbind::example::Apple
     *       name: apples
     *     - type: cppbind::example::Pineapple
     *       name: pineapple
     */
    template <typename T>
    std::vector<T*> fruits() const {
        std::vector<T*> res;
        std::for_each(_fruits.begin(), _fruits.end(), [&res](const auto& f) {
            if (f->type() == T::Type) {
                res.push_back(static_cast<T*>(f));
            }
        });
        return res;
    }

    /**
     * __API__
     * action: gen_getter
     * throws: no_throw
     * template:
     *   T:
     *     - type: cppbind::example::Apple
     *       name: applesWith
     *   U:
     *     - type: cppbind::example::Pineapple
     *       name: Pineapples
     */
    template <typename T, typename U>
    const std::vector<Fruit*> & allFruits() const {
        return _fruits;
    }

    /**
     * __API__
     * action: gen_setter
     * throws: no_throw
     * template:
     *   T:
     *     - type: cppbind::example::Apple
     *   U:
     *     - type: cppbind::example::Pineapple
     */
    template <typename T, typename U>
    void setAllFruits(const std::vector<Fruit*> & fruits) {
        _fruits = fruits;
    }


private:
    std::vector<Fruit*> _fruits;
};

In the above example, we have a template getter fruits, and we have specified two types for parameter T: cppbind::example::Apple and cppbind::example::Pineapple. Notice that the name is specified for both, which is used as a generated property name. As a result, we'll have apple and pineapple correspondingly. If name is not specified, then the target language type name is used. For this example, we would have Apple and Pineapple correspondingly. In the above example, we have another template getter/setter, allFruits with two template parameters, T and U. Again, we have specified name for both parameters. In the case of multiple template parameters, target property name is constructed by joining user-provided names. For this example, it is applesWithPineapples for Kotlin and Swift, apples_with_pineapples for Python. Notice that the name is snake-cased for Python. The API for this getter could also be written in the following way:

T:
  - type: cppbind::example::Apple
    name: applesWithPineapples
U:
  - type: cppbind::example::Pineapple

The result will be the same.

If the name is not specified, the target property name is constructed by joining the names of target language types. For this example, we would have applePineapple (Swift, Kotlin) and apple_pineapple (Python).

And here are some usage examples:

val apple1 = Apple()
val apple2 = Apple()
val papple1 = Pineapple()
val papple2 = Pineapple()
val fruits = Fruits(listOf(apple1, apple2, papple1, papple2))

assert(fruits.apples.size == 2)
assert(fruits.pineapple.size == 2)
var applesPineapples = fruits.applesWithPineapples
assert(applesPineapples.size == 4)
fruits.applesWithPineapples = listOf(papple1, papple2, apple1, apple2)
applesPineapples = fruits.applesWithPineapples
assert(applesPineapples[0].type == FruitType.Pineapple)
assert(applesPineapples[3].type == FruitType.Apple)
apple1 = Apple()
apple2 = Apple()
papple1 = Pineapple()
papple2 = Pineapple()
fruits = Fruits([apple1, apple2, papple1, papple2])

assert len(fruits.apples) == 2
assert len(fruits.pineapple) == 2
apples_pineapples = fruits.apples_with_pineapples
assert len(apples_pineapples) == 4
fruits.apples_with_pineapples = [papple1, papple2, apple1, apple2]
apples_pineapples = fruits.apples_with_pineapples
assert apples_pineapples[0].type == FruitType.Pineapple
assert apples_pineapples[3].type == FruitType.Apple
let apple1 = Apple()
let apple2 = Apple()
let papple1 = Pineapple()
let papple2 = Pineapple()
let fruits = Fruits(fruits: [apple1, apple2, papple1, papple2])

assert(fruits.apples.count == 2)
assert(fruits.pineapple.count == 2)
var applesPineapples = fruits.applesWithPineapples
assert(applesPineapples.count == 4)
fruits.applesWithPineapples = [papple1, papple2, apple1, apple2]
applesPineapples = fruits.applesWithPineapples
assert(applesPineapples[0].type == FruitType.Pineapple)
assert(applesPineapples[3].type == FruitType.Apple)
Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 10/18/2022-09:00.
 * Please do not change it manually.
 */

package com.examples.getters

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*

enum class FruitType(val value: Int) {
    Apple(1),
    Pineapple(2);

    companion object {
        private val values = values()
        fun getByValue(value: Int) = values.firstOrNull { it.value == value }
    }
}

open class Fruit
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Fruit"

        /**
         * An internal method to create a Kotlin object from a C++ object.
         * It is intended to be used by the generated code.
         */
        public fun cppbindConstructObject(id: Long, owner: Boolean = false): Fruit {
            val idType = jGettypebyid(id)
            val obj : Fruit
            when (idType) {
                Apple.cppbindCxxTypeName -> obj = Apple(CppBindObject(id, owner))
                Pineapple.cppbindCxxTypeName -> obj = Pineapple(CppBindObject(id, owner))
                else -> obj = Fruit(CppBindObject(id, owner))
            }
            return obj
        }
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    open val type: FruitType
        get() {
            val result = jType(cppbindObjId)
            val jdktokotlinresultOptional = FruitType.getByValue(result)
            if (jdktokotlinresultOptional == null) {
                ExceptionHandler.handleUncaughtException("Internal error: unresolved reference to non existing field of FruitType enum.")
            }
            val jdktokotlinresult = jdktokotlinresultOptional!!
            return jdktokotlinresult
        }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Fruit
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jType(id: Long): Int
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

open class Apple
internal constructor(obj: CppBindObject) : Fruit(obj) {
    companion object {

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Apple"
    }


    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    open override val type: FruitType
        get() {
            val result = jType(cppbindObjId)
            val jdktokotlinresultOptional = FruitType.getByValue(result)
            if (jdktokotlinresultOptional == null) {
                ExceptionHandler.handleUncaughtException("Internal error: unresolved reference to non existing field of FruitType enum.")
            }
            val jdktokotlinresult = jdktokotlinresultOptional!!
            return jdktokotlinresult
        }

    ///// External wrapper functions ////////////
    private external fun jType(id: Long): Int
}

open class Pineapple
internal constructor(obj: CppBindObject) : Fruit(obj) {
    companion object {

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Pineapple"
    }


    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    open override val type: FruitType
        get() {
            val result = jType(cppbindObjId)
            val jdktokotlinresultOptional = FruitType.getByValue(result)
            if (jdktokotlinresultOptional == null) {
                ExceptionHandler.handleUncaughtException("Internal error: unresolved reference to non existing field of FruitType enum.")
            }
            val jdktokotlinresult = jdktokotlinresultOptional!!
            return jdktokotlinresult
        }

    ///// External wrapper functions ////////////
    private external fun jType(id: Long): Int
}

/**
 * An example class containing template getters.
 */
open class Fruits
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(fruits: List<Fruit>): Long {
            val kotlintojdkfruits = LongArray(fruits.size) 
            var indexFruits = 0
            for (valueFruits in fruits) {
                val kotlintojdkvalueFruits = valueFruits.cppbindObjId
                kotlintojdkfruits[indexFruits] = kotlintojdkvalueFruits
                ++indexFruits
            }
            val id = jConstructor(kotlintojdkfruits, fruits)
            return id
        }

        @JvmStatic
        private external fun jConstructor(fruits: LongArray, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Fruits"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(fruits: List<Fruit>): this(CppBindObject(constructHelper(fruits), true)) {
    }

    open val apples: List<Apple>
        get() {
            val result = jFruitsApple(cppbindObjId)
            val jdktokotlinresult: MutableList<Apple> = mutableListOf()
            for (valueResult in result) {
                val jdktokotlinvalueResult = Apple(CppBindObject(valueResult))
                jdktokotlinresult.add(jdktokotlinvalueResult)
            }
            return jdktokotlinresult
        }

    open val pineapple: List<Pineapple>
        get() {
            val result = jFruitsPineapple(cppbindObjId)
            val jdktokotlinresult: MutableList<Pineapple> = mutableListOf()
            for (valueResult in result) {
                val jdktokotlinvalueResult = Pineapple(CppBindObject(valueResult))
                jdktokotlinresult.add(jdktokotlinvalueResult)
            }
            return jdktokotlinresult
        }

    open var applesWithPineapples: List<Fruit>
        get() {
            val result = jAllfruitsApplePineapple(cppbindObjId)
            val jdktokotlinresult: MutableList<Fruit> = mutableListOf()
            for (valueResult in result) {

                val jdktokotlinvalueResult : Fruit
                jdktokotlinvalueResult = Fruit.cppbindConstructObject(valueResult)
                jdktokotlinresult.add(jdktokotlinvalueResult)
            }
            for (valuejdktokotlinresult in jdktokotlinresult) {
                valuejdktokotlinresult.keepCppBindReference(this)
            }
            return jdktokotlinresult
        }
        set(value) {
            val kotlintojdkvalue = LongArray(value.size) 
            var indexValue = 0
            for (valueValue in value) {
                val kotlintojdkvalueValue = valueValue.cppbindObjId
                kotlintojdkvalue[indexValue] = kotlintojdkvalueValue
                ++indexValue
            }
            jSetallfruitsApplePineapple(cppbindObjId, kotlintojdkvalue, value)
        }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Fruits
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jFruitsApple(id: Long): LongArray
    private external fun jFruitsPineapple(id: Long): LongArray
    private external fun jAllfruitsApplePineapple(id: Long): LongArray
    private external fun jSetallfruitsApplePineapple(id: Long, value: LongArray, valueObj: Any?): Unit
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 08/11/2022-07:34.
Please do not change it manually.
"""
from __future__ import annotations

from abc import abstractmethod
from typing import *

import examples.getters.fruits as pybind_fruits_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *


class FruitType(metaclass=CppBindEnumMetaclass):

    Apple = pybind_fruits_pygen.FruitType.Apple
    Pineapple = pybind_fruits_pygen.FruitType.Pineapple

    def __int__(self):
        return self.value


class Fruit(metaclass=CppBindMetaclass):
    @abstractmethod
    def __init__(self, *args, **kwargs):
        pass

    @property
    @bind
    def type(self) -> FruitType:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class Apple(Fruit, metaclass=CppBindMetaclass):

    @bind
    def __init__(self):

        pass

    @property
    @bind
    def type(self) -> FruitType:

        pass


class Pineapple(Fruit, metaclass=CppBindMetaclass):

    @bind
    def __init__(self):

        pass

    @property
    @bind
    def type(self) -> FruitType:

        pass


class Fruits(metaclass=CppBindMetaclass):
    """
    An example class containing template getters.
    """

    @bind
    def __init__(self, fruits: List[Fruit]):

        pass

    @property
    @bind
    def apples(self) -> List[Apple]:

        pass

    @property
    @bind
    def pineapple(self) -> List[Pineapple]:

        pass

    @property
    @bind
    def apples_with_pineapples(self) -> List[Fruit]:

        pass

    @apples_with_pineapples.setter
    @bind
    def apples_with_pineapples(self, value: List[Fruit]):

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 10/18/2022-08:51.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

public enum FruitType: CInt {
  case Apple = 1
  case Pineapple = 2
}

public class Fruit {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_Fruit(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  /// internal dummy initializer to prevent automatic initializer inheritance
  internal init(_cself: CppBindCObject, _self: Fruit) {
    fatalError("A dummy internal initializer should not be called.")
  }

  public var type: FruitType {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Fruit_type(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")
      }
    }
    guard let sctoswiftresult = FruitType(rawValue: result) else {
       ExceptionHandler.handleUncaughtException(
          "Internal error: unresolved reference to non existing field of FruitType enum.")
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Fruit" }

  /// An internal method to create a Swift object from a C++ object.
  /// It is intended to be used by the generated code.
  class func cppbindConstructObject(_ cppbindObj: CppBindCObject, _ owner: Bool = false) -> Fruit {
    let typeName = String(cString: cppbindObj.type)
    var obj : Fruit
    switch(typeName) {
    case(Apple.cppbindCxxTypeName):
      obj = Apple(cppbindObj, owner)
    case(Pineapple.cppbindCxxTypeName):
      obj = Pineapple(cppbindObj, owner)
    default:
      obj = Fruit(cppbindObj, owner)
    }
    return obj
  }
}

public class Apple: Fruit {
  /// internal main initializer
  internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
    super.init(_cself, _owner)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Apple(&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")
      }
    }
  }

  public override var type: FruitType {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Apple_type(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")
      }
    }
    guard let sctoswiftresult = FruitType(rawValue: result) else {
       ExceptionHandler.handleUncaughtException(
          "Internal error: unresolved reference to non existing field of FruitType enum.")
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  override class var cppbindCxxTypeName : String { return "cppbind::example::Apple" }
}

public class Pineapple: Fruit {
  /// internal main initializer
  internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
    super.init(_cself, _owner)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Pineapple(&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")
      }
    }
  }

  public override var type: FruitType {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Pineapple_type(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")
      }
    }
    guard let sctoswiftresult = FruitType(rawValue: result) else {
       ExceptionHandler.handleUncaughtException(
          "Internal error: unresolved reference to non existing field of FruitType enum.")
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  override class var cppbindCxxTypeName : String { return "cppbind::example::Pineapple" }
}

/// An example class containing template getters.
public class Fruits {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_Fruits(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(fruits: Array<Fruit>) {
    let _swifttoscfruitsData = UnsafeMutablePointer<CppBindCObject>.allocate(capacity: fruits.count)
    var swifttoscfruits = CppBindCDataArray()
    swifttoscfruits.data = UnsafeMutableRawPointer(_swifttoscfruitsData)
    swifttoscfruits.size = Int64(fruits.count)
    for i in 0..<fruits.count {
      let fruitsVal = fruits[i]
      let swifttoscfruitsVal = fruitsVal.cself
      _swifttoscfruitsData[i] = swifttoscfruitsVal
    }
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Fruits(swifttoscfruits, &cppbindErr), true)

    swifttoscfruits.data.deallocate()
    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")
      }
    }
  }

  public var apples: Array<Apple> {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Fruits_fruitsApple(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 _resultBuffer = UnsafeBufferPointer<CppBindCObject>(
      start: result.data.assumingMemoryBound(to: CppBindCObject.self),
      count: Int(result.size))
    var sctoswiftresult: [Apple] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      var sctoswiftresultValue: Apple
      sctoswiftresultValue = Apple(resultValue)
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  public var pineapple: Array<Pineapple> {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Fruits_fruitsPineapple(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 _resultBuffer = UnsafeBufferPointer<CppBindCObject>(
      start: result.data.assumingMemoryBound(to: CppBindCObject.self),
      count: Int(result.size))
    var sctoswiftresult: [Pineapple] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      var sctoswiftresultValue: Pineapple
      sctoswiftresultValue = Pineapple(resultValue)
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  public var applesWithPineapples: Array<Fruit> {
    get {
      var cppbindErr = CppBindCObject()
      let result = _prop_get_CppbindExample_Fruits_allFruitsApplePineapple(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 _resultBuffer = UnsafeBufferPointer<CppBindCObject>(
        start: result.data.assumingMemoryBound(to: CppBindCObject.self),
        count: Int(result.size))
      var sctoswiftresult: [Fruit] = []
      defer {
        _resultBuffer.deallocate()
      }
      for i in 0..<Int(result.size) {
        let resultValue = _resultBuffer[i]
        var sctoswiftresultValue: Fruit
        sctoswiftresultValue = Fruit.cppbindConstructObject(resultValue)
        sctoswiftresult.append(sctoswiftresultValue)
      }
      for valuesctoswiftresult in sctoswiftresult {
        valuesctoswiftresult.keepCppBindReference(self)
      }
      return sctoswiftresult
    }

    set(value) {
      let _swifttoscvalueData = UnsafeMutablePointer<CppBindCObject>.allocate(capacity: value.count)
      var swifttoscvalue = CppBindCDataArray()
      swifttoscvalue.data = UnsafeMutableRawPointer(_swifttoscvalueData)
      swifttoscvalue.size = Int64(value.count)
      for i in 0..<value.count {
        let valueVal = value[i]
        let swifttoscvalueVal = valueVal.cself
        _swifttoscvalueData[i] = swifttoscvalueVal
      }
      var cppbindErr = CppBindCObject()
      _prop_set_CppbindExample_Fruits_allFruitsApplePineapple(cself, swifttoscvalue, &cppbindErr)

      swifttoscvalue.data.deallocate()
      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")
        }
      }
    }
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Fruits" }
}

Non-type Template Parameters

Currently, cppbind supports only integral non-type template parameters. Like a type template parameter all values of non-type parameters should be specified via __API__.

Let's see an example:

/**
 * __API__
 * action: gen_class
 * package: templates
 * template:
 *  SIZE:
 *   - value: 2
 *     name: '2'
 *   - value: 3
 *     name: '3'
 *  T:
 *   - type: float
 *   - type: int
 */
template <typename T = float, std::size_t SIZE = 2>
class Array {

public:

    Array() {}

    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    Array(const cppbind::example::Array<T, SIZE>& array) : _array(array._array) {}

    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    Array(const std::array<T, SIZE> array) : _array(array) {}

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    T& operator[](int idx) {
        return _array[idx];
    }

    const T& operator[](int idx) const {
        return _array[idx];
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    cppbind::example::Array<T, SIZE> operator+(const cppbind::example::Array<T, SIZE>& rhs) const {
        Array res;
        for (int i = 0; i < SIZE; ++i) {
            res[i] = _array[i] + rhs[i];
        }
        return res;
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    cppbind::example::Array<T, SIZE> operator-(const cppbind::example::Array<T, SIZE>& rhs) const {
        Array res;
        for (int i = 0; i < SIZE; ++i) {
            res[i] = _array[i] - rhs[i];
        }
        return res;
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    bool operator==(const cppbind::example::Array<T, SIZE>& rhs) const {
        for (int i = 0; i < SIZE; ++i) {
            if (_array[i] != rhs[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Kotlin equals covers also !=.
     * __API__
     * swift.action: gen_method
     * python.action: gen_method
     * throws: no_throw
     */
    bool operator!=(const cppbind::example::Array<T, SIZE>& rhs) const {
        return !(*this == rhs);
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    const std::array<T, SIZE>& data() const {
        return _array;
    }

private:
    std::array<T, SIZE> _array {};
};

/**
 * An example of template function with an argument of Array<T, 2> type.
 * __API__
 * action: gen_function
 * throws: no_throw
 * package: templates
 * template:
 *  T:
 *   - type: float
 *   - type: int
 */
template<typename T>
T getFirstElement(const cppbind::example::Array<T, 2>& a) {
    return a[0];
}

/**
 *  An example of template function with an argument of Array<int, 2> type.
 * __API__
 * action: gen_function
 * throws: no_throw
 * package: templates
 */
cppbind::example::Array<int, 2> multiplyElements(const cppbind::example::Array<int, 2>& a, int num) {
    std::array<int, 2> res {num * a[0], num * a[1]};
    return res;
}

using ArrayFloat = Array<>;

/**
 * An example of template function with an argument of typedef on Array.
 * __API__
 * action: gen_function
 * throws: no_throw
 * package: templates
 */
ArrayFloat addToElements(const cppbind::example::ArrayFloat& a, int num) {
    std::array<float, 2> res {num + a[0], num + a[1]};
    return res;
}

using ArrayInt = Array<int, 2>;

/**
 * An example of template function with an argument of typedef on Array.
 * __API__
 * action: gen_function
 * throws: no_throw
 * package: templates
 */
ArrayInt addToElements(const ArrayInt& a, int num) {
    std::array<int, 2> res {num + a[0], num + a[1]};
    return res;
}

/**
 * An example of template function with an argument of Array<T, 2> type.
 * __API__
 * action: gen_function
 * throws: no_throw
 * package: templates
 * template_instance:
 *      - args: int, 2
 */
template<typename T, std::size_t SIZE>
T getLastElement(const cppbind::example::Array<T, SIZE>& a) {
    return a[SIZE - 1];
}

static constexpr size_t SIZE = 3;
static constexpr size_t LENGTH3 = SIZE * SIZE;

/**
 * An example with template argument with expression.
 * __API__
 * action: gen_class
 * shared_ref: True
 * package: templates
 */
class Array3 {

public:

    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    Array3(const std::array<float, LENGTH3>& arr): _arr(arr) {}

    const std::array<float, LENGTH3>& arr() {
        return _arr;
    }

private:
    std::array<float, LENGTH3> _arr {};
};

/**
 * An example with template partial specialization.
 * __API__
 * action: gen_class
 * shared_ref: True
 * package: templates
 * template_instance:
 *   - args: float
 *     name: Array4Float
 *   - args: int
 *     name: Array4Int
 */
template <typename T>
class Array<T, 4> {

public:

    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     */
    Array(const std::array<T, 4> array) : _array(array) {}

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    T& operator[](int idx) {
        return _array[idx];
    }

private:
    std::array<T, 4> _array {};
};

As you can see, we have specified all values for both T and SIZE. CppBind generates four types corresponding to each combination of template arguments, i.e., ArrayFloat1, ArrayFloat2, ArrayInt1 and ArrayInt2.

Now let's see some usage examples:

val arrayFloat = ArrayFloat2(listOf(1.0F, 2.0F))
val arrayFloatCopy = ArrayFloat2(arrayFloat)
assert(arrayFloat == arrayFloatCopy)
assert(arrayFloat[0] == 1.0F)
val arrayFloatSum = arrayFloat + arrayFloatCopy
assert(arrayFloatSum.data() == listOf(2.0F, 4.0F))

val arrayInt = ArrayInt2(listOf(1, 2))
val arrayIntCopy = ArrayInt2(arrayInt)
assert(arrayInt == arrayIntCopy)
assert(arrayInt[0] == 1)
val arrayIntSum = arrayInt + arrayIntCopy
assert(arrayIntSum.data() == listOf(2, 4))

// template specialization example
val array4Int = Array4Int(listOf(1, 2, 3, 4))
assert(array4Int[0] == 1)
assert(array4Int[3] == 4)

val array4Float = Array4Float(listOf(1.0F, 2.0F, 3.0F, 4.0F))
assert(array4Float[0] == 1.0F)
assert(array4Float[3] == 4.0F)
array_float = ArrayFloat2([1.0, 2.0])
array_float_copy = ArrayFloat2(array_float)
assert array_float == array_float_copy
assert array_float[0] == 1.0
array_float_sum = array_float + array_float_copy
assert array_float_sum.data() == [2.0, 4.0]

array_int = ArrayInt2([1, 2])
array_int_copy = ArrayInt2(array_int)
assert array_int == array_int_copy
assert array_int[0] == 1
array_int_sum = array_int + array_int_copy
assert array_int_sum.data() == [2, 4]

# template specialization example
array4_int = Array4Int([1, 2, 3, 4])
assert(array4_int[0] == 1)
assert(array4_int[3] == 4)

array4_float = Array4Float([1.0, 2.0, 3.0, 4.0])
assert(array4_float[0] == 1.0)
assert(array4_float[3] == 4.0)
let arrayFloat = ArrayFloat2(array: [1.0, 2.0])
let arrayFloatCopy = ArrayFloat2(array: arrayFloat)
assert(arrayFloat == arrayFloatCopy)
assert(arrayFloat[0] == 1.0)
let arrayFloatSum = arrayFloat + arrayFloatCopy
assert(arrayFloatSum.data() == [2.0, 4.0])

let arrayInt = ArrayInt2(array: [1, 2])
let arrayIntCopy = ArrayInt2(array: arrayInt)
assert(arrayInt == arrayIntCopy)
assert(arrayInt[0] == 1)
let arrayIntSum = arrayInt + arrayIntCopy
assert(arrayIntSum.data() == [2, 4])

// template specialization example
let array4Int = Array4Int(array: [1, 2, 3, 4])
assert(array4Int[0] == 1)
assert(array4Int[3] == 4)

let array4Float = Array4Float(array: [1.0, 2.0, 3.0, 4.0])
assert(array4Float[0] == 1.0)
assert(array4Float[3] == 4.0)
Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 10/14/2022-07:57.
 * Please do not change it manually.
 */

package com.examples.templates

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*

private val INIT = run {
    System.loadLibrary("wrapper_jni");
}

open class ArrayFloat2
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(array: ArrayFloat2): Long {
            val kotlintojdkarray = array.cppbindObjId
            val id = jConstructor(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor(array: Long, vararg extraObjs: Any?): Long

        protected fun constructHelper(array: List<Float>): Long {
            val kotlintojdkarray = FloatArray(array.size) 
            var indexArray = 0
            for (valueArray in array) {

                kotlintojdkarray[indexArray] = valueArray
                ++indexArray
            }
            val id = jConstructor1(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(array: FloatArray, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Array<float, 2>"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(array: ArrayFloat2): this(CppBindObject(constructHelper(array), true)) {
    }

    constructor(array: List<Float>): this(CppBindObject(constructHelper(array), true)) {
    }

    operator fun get(idx: Int): Float {
        val result = jGet(cppbindObjId, idx)

        return result
    }


    operator fun set(idx: Int, value: Float){
        jSet(cppbindObjId, idx, value)
    }

    operator fun plus(rhs: ArrayFloat2): ArrayFloat2 {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jPlus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = ArrayFloat2(CppBindObject(result, true))
        return jdktokotlinresult
    }

    operator fun minus(rhs: ArrayFloat2): ArrayFloat2 {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jMinus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = ArrayFloat2(CppBindObject(result, true))
        return jdktokotlinresult
    }

    override fun equals(other: Any?): Boolean {
        other as ArrayFloat2
        return jEquals(cppbindObjId, other.cppbindObjId, other)
    }

    fun data(): List<Float> {
        val result = jData(cppbindObjId)
        val jdktokotlinresult: MutableList<Float> = mutableListOf()
        for (valueResult in result) {

            jdktokotlinresult.add(valueResult)
        }
        return jdktokotlinresult
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jGet(id: Long, idx: Int, vararg extraObjs: Any?): Float
    private external fun jSet(id: Long, idx: Int, value: Float, vararg extraObjs: Any?)
    private external fun jPlus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jMinus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jEquals(id: Long, rhs: Long, vararg extraObjs: Any?): Boolean
    private external fun jData(id: Long): FloatArray
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

open class ArrayFloat3
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(array: ArrayFloat3): Long {
            val kotlintojdkarray = array.cppbindObjId
            val id = jConstructor(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor(array: Long, vararg extraObjs: Any?): Long

        protected fun constructHelper(array: List<Float>): Long {
            val kotlintojdkarray = FloatArray(array.size) 
            var indexArray = 0
            for (valueArray in array) {

                kotlintojdkarray[indexArray] = valueArray
                ++indexArray
            }
            val id = jConstructor1(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(array: FloatArray, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Array<float, 3>"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(array: ArrayFloat3): this(CppBindObject(constructHelper(array), true)) {
    }

    constructor(array: List<Float>): this(CppBindObject(constructHelper(array), true)) {
    }

    operator fun get(idx: Int): Float {
        val result = jGet(cppbindObjId, idx)

        return result
    }


    operator fun set(idx: Int, value: Float){
        jSet(cppbindObjId, idx, value)
    }

    operator fun plus(rhs: ArrayFloat3): ArrayFloat3 {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jPlus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = ArrayFloat3(CppBindObject(result, true))
        return jdktokotlinresult
    }

    operator fun minus(rhs: ArrayFloat3): ArrayFloat3 {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jMinus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = ArrayFloat3(CppBindObject(result, true))
        return jdktokotlinresult
    }

    override fun equals(other: Any?): Boolean {
        other as ArrayFloat3
        return jEquals(cppbindObjId, other.cppbindObjId, other)
    }

    fun data(): List<Float> {
        val result = jData(cppbindObjId)
        val jdktokotlinresult: MutableList<Float> = mutableListOf()
        for (valueResult in result) {

            jdktokotlinresult.add(valueResult)
        }
        return jdktokotlinresult
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jGet(id: Long, idx: Int, vararg extraObjs: Any?): Float
    private external fun jSet(id: Long, idx: Int, value: Float, vararg extraObjs: Any?)
    private external fun jPlus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jMinus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jEquals(id: Long, rhs: Long, vararg extraObjs: Any?): Boolean
    private external fun jData(id: Long): FloatArray
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

open class ArrayInt2
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(array: ArrayInt2): Long {
            val kotlintojdkarray = array.cppbindObjId
            val id = jConstructor(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor(array: Long, vararg extraObjs: Any?): Long

        protected fun constructHelper(array: List<Int>): Long {
            val kotlintojdkarray = IntArray(array.size) 
            var indexArray = 0
            for (valueArray in array) {

                kotlintojdkarray[indexArray] = valueArray
                ++indexArray
            }
            val id = jConstructor1(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(array: IntArray, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Array<int, 2>"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(array: ArrayInt2): this(CppBindObject(constructHelper(array), true)) {
    }

    constructor(array: List<Int>): this(CppBindObject(constructHelper(array), true)) {
    }

    operator fun get(idx: Int): Int {
        val result = jGet(cppbindObjId, idx)

        return result
    }


    operator fun set(idx: Int, value: Int){
        jSet(cppbindObjId, idx, value)
    }

    operator fun plus(rhs: ArrayInt2): ArrayInt2 {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jPlus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = ArrayInt2(CppBindObject(result, true))
        return jdktokotlinresult
    }

    operator fun minus(rhs: ArrayInt2): ArrayInt2 {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jMinus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = ArrayInt2(CppBindObject(result, true))
        return jdktokotlinresult
    }

    override fun equals(other: Any?): Boolean {
        other as ArrayInt2
        return jEquals(cppbindObjId, other.cppbindObjId, other)
    }

    fun data(): List<Int> {
        val result = jData(cppbindObjId)
        val jdktokotlinresult: MutableList<Int> = mutableListOf()
        for (valueResult in result) {

            jdktokotlinresult.add(valueResult)
        }
        return jdktokotlinresult
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jGet(id: Long, idx: Int, vararg extraObjs: Any?): Int
    private external fun jSet(id: Long, idx: Int, value: Int, vararg extraObjs: Any?)
    private external fun jPlus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jMinus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jEquals(id: Long, rhs: Long, vararg extraObjs: Any?): Boolean
    private external fun jData(id: Long): IntArray
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

open class ArrayInt3
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(array: ArrayInt3): Long {
            val kotlintojdkarray = array.cppbindObjId
            val id = jConstructor(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor(array: Long, vararg extraObjs: Any?): Long

        protected fun constructHelper(array: List<Int>): Long {
            val kotlintojdkarray = IntArray(array.size) 
            var indexArray = 0
            for (valueArray in array) {

                kotlintojdkarray[indexArray] = valueArray
                ++indexArray
            }
            val id = jConstructor1(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor1(array: IntArray, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Array<int, 3>"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(array: ArrayInt3): this(CppBindObject(constructHelper(array), true)) {
    }

    constructor(array: List<Int>): this(CppBindObject(constructHelper(array), true)) {
    }

    operator fun get(idx: Int): Int {
        val result = jGet(cppbindObjId, idx)

        return result
    }


    operator fun set(idx: Int, value: Int){
        jSet(cppbindObjId, idx, value)
    }

    operator fun plus(rhs: ArrayInt3): ArrayInt3 {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jPlus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = ArrayInt3(CppBindObject(result, true))
        return jdktokotlinresult
    }

    operator fun minus(rhs: ArrayInt3): ArrayInt3 {
        val kotlintojdkrhs = rhs.cppbindObjId
        val result = jMinus(cppbindObjId, kotlintojdkrhs, rhs)
        val jdktokotlinresult = ArrayInt3(CppBindObject(result, true))
        return jdktokotlinresult
    }

    override fun equals(other: Any?): Boolean {
        other as ArrayInt3
        return jEquals(cppbindObjId, other.cppbindObjId, other)
    }

    fun data(): List<Int> {
        val result = jData(cppbindObjId)
        val jdktokotlinresult: MutableList<Int> = mutableListOf()
        for (valueResult in result) {

            jdktokotlinresult.add(valueResult)
        }
        return jdktokotlinresult
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jGet(id: Long, idx: Int, vararg extraObjs: Any?): Int
    private external fun jSet(id: Long, idx: Int, value: Int, vararg extraObjs: Any?)
    private external fun jPlus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jMinus(id: Long, rhs: Long, vararg extraObjs: Any?): Long
    private external fun jEquals(id: Long, rhs: Long, vararg extraObjs: Any?): Boolean
    private external fun jData(id: Long): IntArray
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

/**
 * An example of template function with an argument of Array<T, 2> type.
 */
fun getFirstElement(a: ArrayFloat2): Float {
    val kotlintojdka = a.cppbindObjId
    val result = jGetfirstelementFloat(kotlintojdka, a)

    return result
}

/**
 * An example of template function with an argument of Array<T, 2> type.
 */
fun getFirstElement(a: ArrayInt2): Int {
    val kotlintojdka = a.cppbindObjId
    val result = jGetfirstelementInt(kotlintojdka, a)

    return result
}

/**
 * An example of template function with an argument of Array<int, 2> type.
 */
fun multiplyElements(a: ArrayInt2, num: Int): ArrayInt2 {
    val kotlintojdka = a.cppbindObjId
    val result = jMultiplyelements(kotlintojdka, num, a)
    val jdktokotlinresult = ArrayInt2(CppBindObject(result, true))
    return jdktokotlinresult
}

/**
 * An example of template function with an argument of typedef on Array.
 */
fun addToElements(a: ArrayFloat2, num: Int): ArrayFloat2 {
    val kotlintojdka = a.cppbindObjId
    val result = jAddtoelements(kotlintojdka, num, a)
    val jdktokotlinresult = ArrayFloat2(CppBindObject(result, true))
    return jdktokotlinresult
}

/**
 * An example of template function with an argument of typedef on Array.
 */
fun addToElements(a: ArrayInt2, num: Int): ArrayInt2 {
    val kotlintojdka = a.cppbindObjId
    val result = jAddtoelements1(kotlintojdka, num, a)
    val jdktokotlinresult = ArrayInt2(CppBindObject(result, true))
    return jdktokotlinresult
}

/**
 * An example of template function with an argument of Array<T, 2> type.
 */
fun getLastElement(a: ArrayInt2): Int {
    val kotlintojdka = a.cppbindObjId
    val result = jGetlastelementInt2(kotlintojdka, a)

    return result
}

/**
 * An example with template argument with expression.
 */
open class Array3
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(arr: List<Float>): Long {
            val kotlintojdkarr = FloatArray(arr.size) 
            var indexArr = 0
            for (valueArr in arr) {

                kotlintojdkarr[indexArr] = valueArr
                ++indexArr
            }
            val id = jConstructor(kotlintojdkarr, arr)
            return id
        }

        @JvmStatic
        private external fun jConstructor(arr: FloatArray, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Array3"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(arr: List<Float>): this(CppBindObject(constructHelper(arr), true)) {
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Array3
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jGetcxxid(id: Long): Long
}

/**
 * An example with template partial specialization.
 */
open class Array4Float
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(array: List<Float>): Long {
            val kotlintojdkarray = FloatArray(array.size) 
            var indexArray = 0
            for (valueArray in array) {

                kotlintojdkarray[indexArray] = valueArray
                ++indexArray
            }
            val id = jConstructor(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor(array: FloatArray, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Array<float, 4>"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(array: List<Float>): this(CppBindObject(constructHelper(array), true)) {
    }

    operator fun get(idx: Int): Float {
        val result = jGet(cppbindObjId, idx)

        return result
    }


    operator fun set(idx: Int, value: Float){
        jSet(cppbindObjId, idx, value)
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Array4Float
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jGet(id: Long, idx: Int, vararg extraObjs: Any?): Float
    private external fun jSet(id: Long, idx: Int, value: Float, vararg extraObjs: Any?)
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

/**
 * An example with template partial specialization.
 */
open class Array4Int
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(array: List<Int>): Long {
            val kotlintojdkarray = IntArray(array.size) 
            var indexArray = 0
            for (valueArray in array) {

                kotlintojdkarray[indexArray] = valueArray
                ++indexArray
            }
            val id = jConstructor(kotlintojdkarray, array)
            return id
        }

        @JvmStatic
        private external fun jConstructor(array: IntArray, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Array<int, 4>"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(array: List<Int>): this(CppBindObject(constructHelper(array), true)) {
    }

    operator fun get(idx: Int): Int {
        val result = jGet(cppbindObjId, idx)

        return result
    }


    operator fun set(idx: Int, value: Int){
        jSet(cppbindObjId, idx, value)
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Array4Int
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jGet(id: Long, idx: Int, vararg extraObjs: Any?): Int
    private external fun jSet(id: Long, idx: Int, value: Int, vararg extraObjs: Any?)
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

private external fun jGetfirstelementFloat(a: Long, vararg extraObjs: Any?): Float
private external fun jGetfirstelementInt(a: Long, vararg extraObjs: Any?): Int
private external fun jMultiplyelements(a: Long, num: Int, vararg extraObjs: Any?): Long
private external fun jAddtoelements(a: Long, num: Int, vararg extraObjs: Any?): Long
private external fun jAddtoelements1(a: Long, num: Int, vararg extraObjs: Any?): Long
private external fun jGetlastelementInt2(a: Long, vararg extraObjs: Any?): Int

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 10/14/2022-08:36.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.templates.array as pybind_array_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *


class ArrayFloat2(metaclass=CppBindMetaclass):

    @bind
    def __init__(self, array: ArrayFloat2):

        pass

    @bind
    def __init__(self, array: List[float]):

        pass

    @bind
    def __getitem__(self, idx: int) -> float:

        pass

    @bind
    def __setitem__(self, idx: int, value: float):

        pass

    @bind
    def __add__(self, rhs: ArrayFloat2) -> ArrayFloat2:

        pass

    @bind
    def __sub__(self, rhs: ArrayFloat2) -> ArrayFloat2:

        pass

    @bind
    def __eq__(self, rhs: ArrayFloat2) -> bool:

        pass

    @bind
    def __ne__(self, rhs: ArrayFloat2) -> bool:
        """
        Kotlin equals covers also !=.
        """
        pass

    @bind
    def data(self) -> List[float]:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class ArrayFloat3(metaclass=CppBindMetaclass):

    @bind
    def __init__(self, array: ArrayFloat3):

        pass

    @bind
    def __init__(self, array: List[float]):

        pass

    @bind
    def __getitem__(self, idx: int) -> float:

        pass

    @bind
    def __setitem__(self, idx: int, value: float):

        pass

    @bind
    def __add__(self, rhs: ArrayFloat3) -> ArrayFloat3:

        pass

    @bind
    def __sub__(self, rhs: ArrayFloat3) -> ArrayFloat3:

        pass

    @bind
    def __eq__(self, rhs: ArrayFloat3) -> bool:

        pass

    @bind
    def __ne__(self, rhs: ArrayFloat3) -> bool:
        """
        Kotlin equals covers also !=.
        """
        pass

    @bind
    def data(self) -> List[float]:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class ArrayInt2(metaclass=CppBindMetaclass):

    @bind
    def __init__(self, array: ArrayInt2):

        pass

    @bind
    def __init__(self, array: List[int]):

        pass

    @bind
    def __getitem__(self, idx: int) -> int:

        pass

    @bind
    def __setitem__(self, idx: int, value: int):

        pass

    @bind
    def __add__(self, rhs: ArrayInt2) -> ArrayInt2:

        pass

    @bind
    def __sub__(self, rhs: ArrayInt2) -> ArrayInt2:

        pass

    @bind
    def __eq__(self, rhs: ArrayInt2) -> bool:

        pass

    @bind
    def __ne__(self, rhs: ArrayInt2) -> bool:
        """
        Kotlin equals covers also !=.
        """
        pass

    @bind
    def data(self) -> List[int]:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class ArrayInt3(metaclass=CppBindMetaclass):

    @bind
    def __init__(self, array: ArrayInt3):

        pass

    @bind
    def __init__(self, array: List[int]):

        pass

    @bind
    def __getitem__(self, idx: int) -> int:

        pass

    @bind
    def __setitem__(self, idx: int, value: int):

        pass

    @bind
    def __add__(self, rhs: ArrayInt3) -> ArrayInt3:

        pass

    @bind
    def __sub__(self, rhs: ArrayInt3) -> ArrayInt3:

        pass

    @bind
    def __eq__(self, rhs: ArrayInt3) -> bool:

        pass

    @bind
    def __ne__(self, rhs: ArrayInt3) -> bool:
        """
        Kotlin equals covers also !=.
        """
        pass

    @bind
    def data(self) -> List[int]:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


@bind
def get_first_element_float(a: ArrayFloat2) -> float:
    """
    An example of template function with an argument of Array<T, 2> type.
    """
    pass


@bind
def get_first_element_int(a: ArrayInt2) -> int:
    """
    An example of template function with an argument of Array<T, 2> type.
    """
    pass


@bind
def multiply_elements(a: ArrayInt2, num: int) -> ArrayInt2:
    """
    An example of template function with an argument of Array<int, 2> type.
    """
    pass


@bind
def add_to_elements(a: ArrayFloat2, num: int) -> ArrayFloat2:
    """
    An example of template function with an argument of typedef on Array.
    """
    pass


@bind
def add_to_elements1(a: ArrayInt2, num: int) -> ArrayInt2:
    """
    An example of template function with an argument of typedef on Array.
    """
    pass


@bind
def get_last_element_int2(a: ArrayInt2) -> int:
    """
    An example of template function with an argument of Array<T, 2> type.
    """
    pass


class Array3(metaclass=CppBindMetaclass):
    """
    An example with template argument with expression.
    """

    @bind
    def __init__(self, arr: List[float]):

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class Array4Float(metaclass=CppBindMetaclass):
    """
    An example with template partial specialization.
    """

    @bind
    def __init__(self, array: List[float]):

        pass

    @bind
    def __getitem__(self, idx: int) -> float:

        pass

    @bind
    def __setitem__(self, idx: int, value: float):

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class Array4Int(metaclass=CppBindMetaclass):
    """
    An example with template partial specialization.
    """

    @bind
    def __init__(self, array: List[int]):

        pass

    @bind
    def __getitem__(self, idx: int) -> int:

        pass

    @bind
    def __setitem__(self, idx: int, value: int):

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 10/14/2022-08:12.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

public class ArrayFloat2 {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_ArrayFloat2(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(array: ArrayFloat2) {
    let swifttoscarray = array.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_ArrayFloat2(swifttoscarray, &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")
      }
    }
  }

  public convenience init(array: Array<Float>) {
    let _swifttoscarrayData = UnsafeMutablePointer<CFloat>.allocate(capacity: array.count)
    var swifttoscarray = CppBindCDataArray()
    swifttoscarray.data = UnsafeMutableRawPointer(_swifttoscarrayData)
    swifttoscarray.size = Int64(array.count)
    for i in 0..<array.count {
      let arrayVal = array[i]

      _swifttoscarrayData[i] = arrayVal
    }
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_ArrayFloat21(swifttoscarray, &cppbindErr), true)

    swifttoscarray.data.deallocate()
    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")
      }
    }
  }



  public subscript(idx: Int) -> Float {
    get {
      let swifttoscidx = CInt(idx)
      let result = _func_CppbindExample_ArrayFloat2__getitem_(cself, swifttoscidx)
      return result
    }

    set(value) {
      let swifttoscidx = CInt(idx)
      _func_CppbindExample_ArrayFloat2__setitem_(cself, swifttoscidx, value)
    }
  }

  public static func +(cself: ArrayFloat2, rhs: ArrayFloat2) -> ArrayFloat2 {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat2__add_(cself.cself, swifttoscrhs, &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: ArrayFloat2
    sctoswiftresult = ArrayFloat2(result, true)
    return sctoswiftresult
  }

  public static func -(cself: ArrayFloat2, rhs: ArrayFloat2) -> ArrayFloat2 {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat2__sub_(cself.cself, swifttoscrhs, &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: ArrayFloat2
    sctoswiftresult = ArrayFloat2(result, true)
    return sctoswiftresult
  }

  public static func ==(cself: ArrayFloat2, rhs: ArrayFloat2) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat2__eq_(cself.cself, swifttoscrhs, &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
  }

  /// Kotlin equals covers also !=.
  public static func !=(cself: ArrayFloat2, rhs: ArrayFloat2) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat2__ne_(cself.cself, swifttoscrhs, &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 func data() -> Array<Float> {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat2_data(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 _resultBuffer = UnsafeBufferPointer<CFloat>(
      start: result.data.assumingMemoryBound(to: CFloat.self),
      count: Int(result.size))
    var sctoswiftresult: [Float] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]

      sctoswiftresult.append(resultValue)
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Array<float, 2>" }
}

public class ArrayFloat3 {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_ArrayFloat3(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(array: ArrayFloat3) {
    let swifttoscarray = array.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_ArrayFloat3(swifttoscarray, &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")
      }
    }
  }

  public convenience init(array: Array<Float>) {
    let _swifttoscarrayData = UnsafeMutablePointer<CFloat>.allocate(capacity: array.count)
    var swifttoscarray = CppBindCDataArray()
    swifttoscarray.data = UnsafeMutableRawPointer(_swifttoscarrayData)
    swifttoscarray.size = Int64(array.count)
    for i in 0..<array.count {
      let arrayVal = array[i]

      _swifttoscarrayData[i] = arrayVal
    }
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_ArrayFloat31(swifttoscarray, &cppbindErr), true)

    swifttoscarray.data.deallocate()
    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")
      }
    }
  }



  public subscript(idx: Int) -> Float {
    get {
      let swifttoscidx = CInt(idx)
      let result = _func_CppbindExample_ArrayFloat3__getitem_(cself, swifttoscidx)
      return result
    }

    set(value) {
      let swifttoscidx = CInt(idx)
      _func_CppbindExample_ArrayFloat3__setitem_(cself, swifttoscidx, value)
    }
  }

  public static func +(cself: ArrayFloat3, rhs: ArrayFloat3) -> ArrayFloat3 {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat3__add_(cself.cself, swifttoscrhs, &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: ArrayFloat3
    sctoswiftresult = ArrayFloat3(result, true)
    return sctoswiftresult
  }

  public static func -(cself: ArrayFloat3, rhs: ArrayFloat3) -> ArrayFloat3 {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat3__sub_(cself.cself, swifttoscrhs, &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: ArrayFloat3
    sctoswiftresult = ArrayFloat3(result, true)
    return sctoswiftresult
  }

  public static func ==(cself: ArrayFloat3, rhs: ArrayFloat3) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat3__eq_(cself.cself, swifttoscrhs, &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
  }

  /// Kotlin equals covers also !=.
  public static func !=(cself: ArrayFloat3, rhs: ArrayFloat3) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat3__ne_(cself.cself, swifttoscrhs, &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 func data() -> Array<Float> {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayFloat3_data(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 _resultBuffer = UnsafeBufferPointer<CFloat>(
      start: result.data.assumingMemoryBound(to: CFloat.self),
      count: Int(result.size))
    var sctoswiftresult: [Float] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]

      sctoswiftresult.append(resultValue)
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Array<float, 3>" }
}

public class ArrayInt2 {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_ArrayInt2(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(array: ArrayInt2) {
    let swifttoscarray = array.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_ArrayInt2(swifttoscarray, &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")
      }
    }
  }

  public convenience init(array: Array<Int>) {
    let _swifttoscarrayData = UnsafeMutablePointer<CInt>.allocate(capacity: array.count)
    var swifttoscarray = CppBindCDataArray()
    swifttoscarray.data = UnsafeMutableRawPointer(_swifttoscarrayData)
    swifttoscarray.size = Int64(array.count)
    for i in 0..<array.count {
      let arrayVal = array[i]
      let swifttoscarrayVal = CInt(arrayVal)
      _swifttoscarrayData[i] = swifttoscarrayVal
    }
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_ArrayInt21(swifttoscarray, &cppbindErr), true)

    swifttoscarray.data.deallocate()
    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")
      }
    }
  }



  public subscript(idx: Int) -> Int {
    get {
      let swifttoscidx = CInt(idx)
      let result = _func_CppbindExample_ArrayInt2__getitem_(cself, swifttoscidx)
      let sctoswiftresult = Int(result)
      return sctoswiftresult
    }

    set(value) {
      let swifttoscidx = CInt(idx)
      let swifttoscvalue = CInt(value)
      _func_CppbindExample_ArrayInt2__setitem_(cself, swifttoscidx, swifttoscvalue)
    }
  }

  public static func +(cself: ArrayInt2, rhs: ArrayInt2) -> ArrayInt2 {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt2__add_(cself.cself, swifttoscrhs, &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: ArrayInt2
    sctoswiftresult = ArrayInt2(result, true)
    return sctoswiftresult
  }

  public static func -(cself: ArrayInt2, rhs: ArrayInt2) -> ArrayInt2 {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt2__sub_(cself.cself, swifttoscrhs, &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: ArrayInt2
    sctoswiftresult = ArrayInt2(result, true)
    return sctoswiftresult
  }

  public static func ==(cself: ArrayInt2, rhs: ArrayInt2) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt2__eq_(cself.cself, swifttoscrhs, &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
  }

  /// Kotlin equals covers also !=.
  public static func !=(cself: ArrayInt2, rhs: ArrayInt2) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt2__ne_(cself.cself, swifttoscrhs, &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 func data() -> Array<Int> {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt2_data(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 _resultBuffer = UnsafeBufferPointer<CInt>(
      start: result.data.assumingMemoryBound(to: CInt.self),
      count: Int(result.size))
    var sctoswiftresult: [Int] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      let sctoswiftresultValue = Int(resultValue)
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Array<int, 2>" }
}

public class ArrayInt3 {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_ArrayInt3(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(array: ArrayInt3) {
    let swifttoscarray = array.cself
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_ArrayInt3(swifttoscarray, &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")
      }
    }
  }

  public convenience init(array: Array<Int>) {
    let _swifttoscarrayData = UnsafeMutablePointer<CInt>.allocate(capacity: array.count)
    var swifttoscarray = CppBindCDataArray()
    swifttoscarray.data = UnsafeMutableRawPointer(_swifttoscarrayData)
    swifttoscarray.size = Int64(array.count)
    for i in 0..<array.count {
      let arrayVal = array[i]
      let swifttoscarrayVal = CInt(arrayVal)
      _swifttoscarrayData[i] = swifttoscarrayVal
    }
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_ArrayInt31(swifttoscarray, &cppbindErr), true)

    swifttoscarray.data.deallocate()
    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")
      }
    }
  }



  public subscript(idx: Int) -> Int {
    get {
      let swifttoscidx = CInt(idx)
      let result = _func_CppbindExample_ArrayInt3__getitem_(cself, swifttoscidx)
      let sctoswiftresult = Int(result)
      return sctoswiftresult
    }

    set(value) {
      let swifttoscidx = CInt(idx)
      let swifttoscvalue = CInt(value)
      _func_CppbindExample_ArrayInt3__setitem_(cself, swifttoscidx, swifttoscvalue)
    }
  }

  public static func +(cself: ArrayInt3, rhs: ArrayInt3) -> ArrayInt3 {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt3__add_(cself.cself, swifttoscrhs, &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: ArrayInt3
    sctoswiftresult = ArrayInt3(result, true)
    return sctoswiftresult
  }

  public static func -(cself: ArrayInt3, rhs: ArrayInt3) -> ArrayInt3 {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt3__sub_(cself.cself, swifttoscrhs, &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: ArrayInt3
    sctoswiftresult = ArrayInt3(result, true)
    return sctoswiftresult
  }

  public static func ==(cself: ArrayInt3, rhs: ArrayInt3) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt3__eq_(cself.cself, swifttoscrhs, &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
  }

  /// Kotlin equals covers also !=.
  public static func !=(cself: ArrayInt3, rhs: ArrayInt3) -> Bool {
    let swifttoscrhs = rhs.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt3__ne_(cself.cself, swifttoscrhs, &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 func data() -> Array<Int> {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_ArrayInt3_data(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 _resultBuffer = UnsafeBufferPointer<CInt>(
      start: result.data.assumingMemoryBound(to: CInt.self),
      count: Int(result.size))
    var sctoswiftresult: [Int] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      let sctoswiftresultValue = Int(resultValue)
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Array<int, 3>" }
}

/// An example of template function with an argument of Array<T, 2> type.
public func getFirstElement(a: ArrayFloat2) -> Float {
  let swifttosca = a.cself
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_getFirstElementFloat(swifttosca, &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
}

/// An example of template function with an argument of Array<T, 2> type.
public func getFirstElement(a: ArrayInt2) -> Int {
  let swifttosca = a.cself
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_getFirstElementInt(swifttosca, &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
}

/// An example of template function with an argument of Array<int, 2> type.
public func multiplyElements(a: ArrayInt2, num: Int) -> ArrayInt2 {
  let swifttosca = a.cself
  let swifttoscnum = CInt(num)
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_multiplyElements(swifttosca, swifttoscnum, &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: ArrayInt2
  sctoswiftresult = ArrayInt2(result, true)
  return sctoswiftresult
}

/// An example of template function with an argument of typedef on Array.
public func addToElements(a: ArrayFloat2, num: Int) -> ArrayFloat2 {
  let swifttosca = a.cself
  let swifttoscnum = CInt(num)
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_addToElements(swifttosca, swifttoscnum, &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: ArrayFloat2
  sctoswiftresult = ArrayFloat2(result, true)
  return sctoswiftresult
}

/// An example of template function with an argument of typedef on Array.
public func addToElements(a: ArrayInt2, num: Int) -> ArrayInt2 {
  let swifttosca = a.cself
  let swifttoscnum = CInt(num)
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_addToElements1(swifttosca, swifttoscnum, &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: ArrayInt2
  sctoswiftresult = ArrayInt2(result, true)
  return sctoswiftresult
}

/// An example of template function with an argument of Array<T, 2> type.
public func getLastElement(a: ArrayInt2) -> Int {
  let swifttosca = a.cself
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_getLastElementInt2(swifttosca, &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
}

/// An example with template argument with expression.
public class Array3 {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_Array3(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(arr: Array<Float>) {
    let _swifttoscarrData = UnsafeMutablePointer<CFloat>.allocate(capacity: arr.count)
    var swifttoscarr = CppBindCDataArray()
    swifttoscarr.data = UnsafeMutableRawPointer(_swifttoscarrData)
    swifttoscarr.size = Int64(arr.count)
    for i in 0..<arr.count {
      let arrVal = arr[i]

      _swifttoscarrData[i] = arrVal
    }
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Array3(swifttoscarr, &cppbindErr), true)

    swifttoscarr.data.deallocate()
    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")
      }
    }
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Array3" }
}

/// An example with template partial specialization.
public class Array4Float {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_Array4Float(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(array: Array<Float>) {
    let _swifttoscarrayData = UnsafeMutablePointer<CFloat>.allocate(capacity: array.count)
    var swifttoscarray = CppBindCDataArray()
    swifttoscarray.data = UnsafeMutableRawPointer(_swifttoscarrayData)
    swifttoscarray.size = Int64(array.count)
    for i in 0..<array.count {
      let arrayVal = array[i]

      _swifttoscarrayData[i] = arrayVal
    }
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Array4Float(swifttoscarray, &cppbindErr), true)

    swifttoscarray.data.deallocate()
    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")
      }
    }
  }



  public subscript(idx: Int) -> Float {
    get {
      let swifttoscidx = CInt(idx)
      let result = _func_CppbindExample_Array4Float__getitem_(cself, swifttoscidx)
      return result
    }

    set(value) {
      let swifttoscidx = CInt(idx)
      _func_CppbindExample_Array4Float__setitem_(cself, swifttoscidx, value)
    }
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Array<float, 4>" }
}

/// An example with template partial specialization.
public class Array4Int {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_Array4Int(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(array: Array<Int>) {
    let _swifttoscarrayData = UnsafeMutablePointer<CInt>.allocate(capacity: array.count)
    var swifttoscarray = CppBindCDataArray()
    swifttoscarray.data = UnsafeMutableRawPointer(_swifttoscarrayData)
    swifttoscarray.size = Int64(array.count)
    for i in 0..<array.count {
      let arrayVal = array[i]
      let swifttoscarrayVal = CInt(arrayVal)
      _swifttoscarrayData[i] = swifttoscarrayVal
    }
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Array4Int(swifttoscarray, &cppbindErr), true)

    swifttoscarray.data.deallocate()
    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")
      }
    }
  }



  public subscript(idx: Int) -> Int {
    get {
      let swifttoscidx = CInt(idx)
      let result = _func_CppbindExample_Array4Int__getitem_(cself, swifttoscidx)
      let sctoswiftresult = Int(result)
      return sctoswiftresult
    }

    set(value) {
      let swifttoscidx = CInt(idx)
      let swifttoscvalue = CInt(value)
      _func_CppbindExample_Array4Int__setitem_(cself, swifttoscidx, swifttoscvalue)
    }
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Array<int, 4>" }
}

Variadic Template Parameters

Variadic templates are supported in the same way as regular templates, i.e., users should specify all variations they want to expose.

Let's take a look at the following example.

  /**
   * __API__
   * action: gen_class
   * package: templates
   * include_cxx:
   *  - <vector>
   * template_instance:
   *     - args: std::vector<int>, int, int
   *       name: ElementsInt
   *     - args: std::vector<std::string>, std::string, std::string, std::string
   *       name: ElementsString
   *     - args: std::vector<double>
   *       name: ElementsEmpty
   */
  template <class T, class... Ts>
  struct elements {
      /**
       * __API__
       * action: gen_method
       * throws: no_throw
       */
      static cppbind::example::elements<T, Ts...>* create(Ts... ts) {
          auto self = new elements(ts...);
          return self;
      }

      /**
       * __API__
       * action: gen_getter
       * throws: no_throw
       */
      const T& holder() {
          return *_holder;
      }

  private:
      elements(Ts... ts): _holder(new T({ts...})) {}
      T* _holder;
  };

Note

Only the template_instance variable can be used to expose instances for variadic templates.

In the above example we specified three instantiations for elements struct, thus we will have three generated types in each target language.

Let's take a look at some usage examples:

val elemsInt = ElementsInt.create(1, 2)
val holderInt = elemsInt.holder

assert(holderInt.size == 2)
assert(holderInt[0] == 1)
assert(holderInt[1] == 2)

val elemsString = ElementsString.create("a", "b", "c")
val holderString = elemsString.holder

assert(holderString.size == 3)
assert(holderString[0] == "a")
assert(holderString[2] == "c")

val elemsEmpty = ElementsEmpty.create()
assert(elemsEmpty.holder.size == 0)
elems_int = ElementsInt.create(1, 2)
holder_int = elems_int.holder

assert len(holder_int) == 2
assert holder_int[0] == 1
assert holder_int[1] == 2

elems_string = ElementsString.create("a", "b", "c")
holder_string = elems_string.holder

assert len(holder_string) == 3
assert holder_string[0] == "a"
assert holder_string[2] == "c"

elems_empty = ElementsEmpty.create()
assert len(elems_empty.holder) == 0

# [variadic-examples-end]

# [tuple-examples-start]
tuple_double_int = TupleDoubleInt(1, 1.0)
assert tuple_double_int.tail == 1
assert tuple_double_int.rest.tail == 1.0

tuple_three_int = TupleThreeInt(1, 2, 3)
assert tuple_three_int.tail == 1
assert tuple_three_int.rest.tail == 2
assert tuple_three_int.rest.rest.tail == 3

tuple_two_int = TupleTwoInt(1, 2)
assert tuple_two_int.tail == 1
assert tuple_two_int.rest.tail == 2
# [tuple-examples-end]

# tuple other usage examples
ints_tuple = IntsTuple(1, 2, 3)
assert ints_tuple.tail == 1
assert ints_tuple.rest.tail == 2
assert ints_tuple.rest.rest.tail == 3

my_tuple_double = MyTupleDouble(1.0, 5.0)
assert my_tuple_double.tail == 1.0
assert my_tuple_double.rest.tail == 5.0

my_tuple_int = MyTupleInt(1, 2)
assert my_tuple_int.tail == 1
assert my_tuple_int.rest.tail == 2

assert get_tuple_first_element_int_double(tuple_double_int) == 1
assert get_tuple_first_element_int_int(tuple_two_int) == 1

# check array as an arg and return value
assert get_first_element_int(array_int) == 1
assert get_last_element_int2(array_int) == 2

arrayMultiplied = multiply_elements(array_int, 2)
assert arrayMultiplied.data() == [2, 4]

# check templated constructor
value_obj = TemplateValue(1)
assert value_obj.add_value(2) == 3
value_obj = TemplateValue("a")
assert value_obj.add_value("b") == "ab"

# check type derived from a template
my_stack = MyStackProject()
assert my_stack.empty()
my_stack.push(prj)
assert my_stack.empty() is False
assert my_stack.top().title == prj.title
my_stack.pop()
assert my_stack.empty()
let elemsInt = ElementsInt.create(ts1: 1, ts2: 2)
let holderInt = elemsInt.holder

assert(holderInt.count == 2)
assert(holderInt[0] == 1)
assert(holderInt[1] == 2)

let elemsString = ElementsString.create(ts1: "a", ts2: "b", ts3: "c")
let holderString = elemsString.holder

assert(holderString.count == 3)
assert(holderString[0] == "a")
assert(holderString[2] == "c")

let elemsEmpty = ElementsEmpty.create()
assert(elemsEmpty.holder.count == 0)
// [variadic-examples-end]

// check array as an arg and return letue
// [tuple-examples-start]
let tupleDoubleInt = TupleDoubleInt(t: 1, ts1: 1.0)
assert(tupleDoubleInt.tail == 1)
assert(tupleDoubleInt.rest.tail == 1.0)

let tupleThreeInt = TupleThreeInt(t: 1, ts1: 2, ts2: 3)
assert(tupleThreeInt.tail == 1)
assert(tupleThreeInt.rest.tail == 2)
assert(tupleThreeInt.rest.rest.tail == 3)

let tupleTwoInt = TupleTwoInt(t: 1, ts1: 2)
assert(tupleTwoInt.tail == 1)
assert(tupleTwoInt.rest.tail == 2)
// [tuple-examples-end]

// tuple other usage examples
let intsTuple = IntsTuple(a: 1, b: 2, c: 3)
assert(intsTuple.tail == 1)
assert(intsTuple.rest.tail == 2)
assert(intsTuple.rest.rest.tail == 3)

let myTupleDouble = MyTupleDouble(a: 1.0, b: 5.0)
assert(myTupleDouble.tail == 1.0)
assert(myTupleDouble.rest.tail == 5.0)

let myTupleInt = MyTupleInt(a: 1, b: 2)
assert(myTupleInt.tail == 1)
assert(myTupleInt.rest.tail == 2)

assert(getTupleFirstElement(t1: tupleDoubleInt) == 1)
assert(getTupleFirstElement(t1: tupleTwoInt) == 1)

// check array as an arg and return value
assert(getFirstElement(a: arrayInt) == 1)
assert(getLastElement(a: arrayInt) == 2)
let arrayMultiplied = multiplyElements(a: arrayInt, num: 2)
assert(arrayMultiplied.data() == [2, 4])

// check templated constructor
var valueObj = TemplateValue(value: 1)
assert(valueObj.add_value(other: 2) == 3)
valueObj = TemplateValue(value: "a")
assert(valueObj.add_value(other: "b") == "ab")

// check type derived from a template
let myStack = MyStackProject()
assert(myStack.empty())
myStack.push(item: prj)
assert(!myStack.empty())
assert(myStack.top().title == prj.title)
myStack.pop()
assert(myStack.empty())

}


#if os(Linux)
runTemplateExamples()
#elseif os(OSX)
class TemplatesTests: XCTestCase {

    func testRun() throws {
        runTemplateExamples()
    }
}
#endif
Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 10/18/2022-09:00.
 * Please do not change it manually.
 */

package com.examples.getters

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*

enum class FruitType(val value: Int) {
    Apple(1),
    Pineapple(2);

    companion object {
        private val values = values()
        fun getByValue(value: Int) = values.firstOrNull { it.value == value }
    }
}

open class Fruit
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Fruit"

        /**
         * An internal method to create a Kotlin object from a C++ object.
         * It is intended to be used by the generated code.
         */
        public fun cppbindConstructObject(id: Long, owner: Boolean = false): Fruit {
            val idType = jGettypebyid(id)
            val obj : Fruit
            when (idType) {
                Apple.cppbindCxxTypeName -> obj = Apple(CppBindObject(id, owner))
                Pineapple.cppbindCxxTypeName -> obj = Pineapple(CppBindObject(id, owner))
                else -> obj = Fruit(CppBindObject(id, owner))
            }
            return obj
        }
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    open val type: FruitType
        get() {
            val result = jType(cppbindObjId)
            val jdktokotlinresultOptional = FruitType.getByValue(result)
            if (jdktokotlinresultOptional == null) {
                ExceptionHandler.handleUncaughtException("Internal error: unresolved reference to non existing field of FruitType enum.")
            }
            val jdktokotlinresult = jdktokotlinresultOptional!!
            return jdktokotlinresult
        }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Fruit
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jType(id: Long): Int
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

open class Apple
internal constructor(obj: CppBindObject) : Fruit(obj) {
    companion object {

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Apple"
    }


    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    open override val type: FruitType
        get() {
            val result = jType(cppbindObjId)
            val jdktokotlinresultOptional = FruitType.getByValue(result)
            if (jdktokotlinresultOptional == null) {
                ExceptionHandler.handleUncaughtException("Internal error: unresolved reference to non existing field of FruitType enum.")
            }
            val jdktokotlinresult = jdktokotlinresultOptional!!
            return jdktokotlinresult
        }

    ///// External wrapper functions ////////////
    private external fun jType(id: Long): Int
}

open class Pineapple
internal constructor(obj: CppBindObject) : Fruit(obj) {
    companion object {

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Pineapple"
    }


    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    open override val type: FruitType
        get() {
            val result = jType(cppbindObjId)
            val jdktokotlinresultOptional = FruitType.getByValue(result)
            if (jdktokotlinresultOptional == null) {
                ExceptionHandler.handleUncaughtException("Internal error: unresolved reference to non existing field of FruitType enum.")
            }
            val jdktokotlinresult = jdktokotlinresultOptional!!
            return jdktokotlinresult
        }

    ///// External wrapper functions ////////////
    private external fun jType(id: Long): Int
}

/**
 * An example class containing template getters.
 */
open class Fruits
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(fruits: List<Fruit>): Long {
            val kotlintojdkfruits = LongArray(fruits.size) 
            var indexFruits = 0
            for (valueFruits in fruits) {
                val kotlintojdkvalueFruits = valueFruits.cppbindObjId
                kotlintojdkfruits[indexFruits] = kotlintojdkvalueFruits
                ++indexFruits
            }
            val id = jConstructor(kotlintojdkfruits, fruits)
            return id
        }

        @JvmStatic
        private external fun jConstructor(fruits: LongArray, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Fruits"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(fruits: List<Fruit>): this(CppBindObject(constructHelper(fruits), true)) {
    }

    open val apples: List<Apple>
        get() {
            val result = jFruitsApple(cppbindObjId)
            val jdktokotlinresult: MutableList<Apple> = mutableListOf()
            for (valueResult in result) {
                val jdktokotlinvalueResult = Apple(CppBindObject(valueResult))
                jdktokotlinresult.add(jdktokotlinvalueResult)
            }
            return jdktokotlinresult
        }

    open val pineapple: List<Pineapple>
        get() {
            val result = jFruitsPineapple(cppbindObjId)
            val jdktokotlinresult: MutableList<Pineapple> = mutableListOf()
            for (valueResult in result) {
                val jdktokotlinvalueResult = Pineapple(CppBindObject(valueResult))
                jdktokotlinresult.add(jdktokotlinvalueResult)
            }
            return jdktokotlinresult
        }

    open var applesWithPineapples: List<Fruit>
        get() {
            val result = jAllfruitsApplePineapple(cppbindObjId)
            val jdktokotlinresult: MutableList<Fruit> = mutableListOf()
            for (valueResult in result) {

                val jdktokotlinvalueResult : Fruit
                jdktokotlinvalueResult = Fruit.cppbindConstructObject(valueResult)
                jdktokotlinresult.add(jdktokotlinvalueResult)
            }
            for (valuejdktokotlinresult in jdktokotlinresult) {
                valuejdktokotlinresult.keepCppBindReference(this)
            }
            return jdktokotlinresult
        }
        set(value) {
            val kotlintojdkvalue = LongArray(value.size) 
            var indexValue = 0
            for (valueValue in value) {
                val kotlintojdkvalueValue = valueValue.cppbindObjId
                kotlintojdkvalue[indexValue] = kotlintojdkvalueValue
                ++indexValue
            }
            jSetallfruitsApplePineapple(cppbindObjId, kotlintojdkvalue, value)
        }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Fruits
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    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 jFruitsApple(id: Long): LongArray
    private external fun jFruitsPineapple(id: Long): LongArray
    private external fun jAllfruitsApplePineapple(id: Long): LongArray
    private external fun jSetallfruitsApplePineapple(id: Long, value: LongArray, valueObj: Any?): Unit
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 08/11/2022-07:34.
Please do not change it manually.
"""
from __future__ import annotations

from abc import abstractmethod
from typing import *

import examples.getters.fruits as pybind_fruits_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *


class FruitType(metaclass=CppBindEnumMetaclass):

    Apple = pybind_fruits_pygen.FruitType.Apple
    Pineapple = pybind_fruits_pygen.FruitType.Pineapple

    def __int__(self):
        return self.value


class Fruit(metaclass=CppBindMetaclass):
    @abstractmethod
    def __init__(self, *args, **kwargs):
        pass

    @property
    @bind
    def type(self) -> FruitType:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class Apple(Fruit, metaclass=CppBindMetaclass):

    @bind
    def __init__(self):

        pass

    @property
    @bind
    def type(self) -> FruitType:

        pass


class Pineapple(Fruit, metaclass=CppBindMetaclass):

    @bind
    def __init__(self):

        pass

    @property
    @bind
    def type(self) -> FruitType:

        pass


class Fruits(metaclass=CppBindMetaclass):
    """
    An example class containing template getters.
    """

    @bind
    def __init__(self, fruits: List[Fruit]):

        pass

    @property
    @bind
    def apples(self) -> List[Apple]:

        pass

    @property
    @bind
    def pineapple(self) -> List[Pineapple]:

        pass

    @property
    @bind
    def apples_with_pineapples(self) -> List[Fruit]:

        pass

    @apples_with_pineapples.setter
    @bind
    def apples_with_pineapples(self, value: List[Fruit]):

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 10/18/2022-08:51.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

public enum FruitType: CInt {
  case Apple = 1
  case Pineapple = 2
}

public class Fruit {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_Fruit(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  /// internal dummy initializer to prevent automatic initializer inheritance
  internal init(_cself: CppBindCObject, _self: Fruit) {
    fatalError("A dummy internal initializer should not be called.")
  }

  public var type: FruitType {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Fruit_type(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")
      }
    }
    guard let sctoswiftresult = FruitType(rawValue: result) else {
       ExceptionHandler.handleUncaughtException(
          "Internal error: unresolved reference to non existing field of FruitType enum.")
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Fruit" }

  /// An internal method to create a Swift object from a C++ object.
  /// It is intended to be used by the generated code.
  class func cppbindConstructObject(_ cppbindObj: CppBindCObject, _ owner: Bool = false) -> Fruit {
    let typeName = String(cString: cppbindObj.type)
    var obj : Fruit
    switch(typeName) {
    case(Apple.cppbindCxxTypeName):
      obj = Apple(cppbindObj, owner)
    case(Pineapple.cppbindCxxTypeName):
      obj = Pineapple(cppbindObj, owner)
    default:
      obj = Fruit(cppbindObj, owner)
    }
    return obj
  }
}

public class Apple: Fruit {
  /// internal main initializer
  internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
    super.init(_cself, _owner)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Apple(&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")
      }
    }
  }

  public override var type: FruitType {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Apple_type(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")
      }
    }
    guard let sctoswiftresult = FruitType(rawValue: result) else {
       ExceptionHandler.handleUncaughtException(
          "Internal error: unresolved reference to non existing field of FruitType enum.")
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  override class var cppbindCxxTypeName : String { return "cppbind::example::Apple" }
}

public class Pineapple: Fruit {
  /// internal main initializer
  internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
    super.init(_cself, _owner)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Pineapple(&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")
      }
    }
  }

  public override var type: FruitType {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Pineapple_type(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")
      }
    }
    guard let sctoswiftresult = FruitType(rawValue: result) else {
       ExceptionHandler.handleUncaughtException(
          "Internal error: unresolved reference to non existing field of FruitType enum.")
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  override class var cppbindCxxTypeName : String { return "cppbind::example::Pineapple" }
}

/// An example class containing template getters.
public class Fruits {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  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_Fruits(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(fruits: Array<Fruit>) {
    let _swifttoscfruitsData = UnsafeMutablePointer<CppBindCObject>.allocate(capacity: fruits.count)
    var swifttoscfruits = CppBindCDataArray()
    swifttoscfruits.data = UnsafeMutableRawPointer(_swifttoscfruitsData)
    swifttoscfruits.size = Int64(fruits.count)
    for i in 0..<fruits.count {
      let fruitsVal = fruits[i]
      let swifttoscfruitsVal = fruitsVal.cself
      _swifttoscfruitsData[i] = swifttoscfruitsVal
    }
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Fruits(swifttoscfruits, &cppbindErr), true)

    swifttoscfruits.data.deallocate()
    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")
      }
    }
  }

  public var apples: Array<Apple> {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Fruits_fruitsApple(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 _resultBuffer = UnsafeBufferPointer<CppBindCObject>(
      start: result.data.assumingMemoryBound(to: CppBindCObject.self),
      count: Int(result.size))
    var sctoswiftresult: [Apple] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      var sctoswiftresultValue: Apple
      sctoswiftresultValue = Apple(resultValue)
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  public var pineapple: Array<Pineapple> {
    var cppbindErr = CppBindCObject()
    let result = _prop_get_CppbindExample_Fruits_fruitsPineapple(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 _resultBuffer = UnsafeBufferPointer<CppBindCObject>(
      start: result.data.assumingMemoryBound(to: CppBindCObject.self),
      count: Int(result.size))
    var sctoswiftresult: [Pineapple] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      var sctoswiftresultValue: Pineapple
      sctoswiftresultValue = Pineapple(resultValue)
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  public var applesWithPineapples: Array<Fruit> {
    get {
      var cppbindErr = CppBindCObject()
      let result = _prop_get_CppbindExample_Fruits_allFruitsApplePineapple(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 _resultBuffer = UnsafeBufferPointer<CppBindCObject>(
        start: result.data.assumingMemoryBound(to: CppBindCObject.self),
        count: Int(result.size))
      var sctoswiftresult: [Fruit] = []
      defer {
        _resultBuffer.deallocate()
      }
      for i in 0..<Int(result.size) {
        let resultValue = _resultBuffer[i]
        var sctoswiftresultValue: Fruit
        sctoswiftresultValue = Fruit.cppbindConstructObject(resultValue)
        sctoswiftresult.append(sctoswiftresultValue)
      }
      for valuesctoswiftresult in sctoswiftresult {
        valuesctoswiftresult.keepCppBindReference(self)
      }
      return sctoswiftresult
    }

    set(value) {
      let _swifttoscvalueData = UnsafeMutablePointer<CppBindCObject>.allocate(capacity: value.count)
      var swifttoscvalue = CppBindCDataArray()
      swifttoscvalue.data = UnsafeMutableRawPointer(_swifttoscvalueData)
      swifttoscvalue.size = Int64(value.count)
      for i in 0..<value.count {
        let valueVal = value[i]
        let swifttoscvalueVal = valueVal.cself
        _swifttoscvalueData[i] = swifttoscvalueVal
      }
      var cppbindErr = CppBindCObject()
      _prop_set_CppbindExample_Fruits_allFruitsApplePineapple(cself, swifttoscvalue, &cppbindErr)

      swifttoscvalue.data.deallocate()
      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")
        }
      }
    }
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Fruits" }
}

Last update: December 1, 2022