Skip to content
brett hartshorn edited this page Jan 22, 2015 · 3 revisions

C++ Backend Generics

Below myfunc is defined twice, in each definition x is given a different type, int and string.

def myfunc( x:int ):
	print( x * 100 )

def myfunc( x:string ):
	print( x + 'world' )

Now myfunc can be called with an int or string type.

def main():
	myfunc( 10 )
	myfunc( 'hello' )

https://github.com/rusthon/Rusthon/blob/master/regtests/c%2B%2B/generics.py

Subclasses

Manually redefining the function for each type of argument type combination quickly becomes tedious, like above. As a special case for dealing with sub-classes that share a common base class, Rusthon will regenerate the function for you with each possible combination of the sub-classes for the function arguments. This requires that methods and data members accessed inside the function body all conform to the same type interface.

class A:
	def __init__(self, x:int): self.x = x
	def method1(self) -> int: return self.x

class B(A):
	def method1(self) ->int: return self.x * 2

class C(A):
	def method1(self) ->int: return self.x + 200

Here is how to manually define a generic function my_generic that takes any type of A:

def my_generic( g:A ) ->int:
    return g.method1()
def my_generic( g:B ) ->int:
    return g.method1()
def my_generic( g:C ) ->int:
    return g.method1()

Above is the C++ style of doing generics, but it is not very pythonic. In this case where the function body is the same for each argument type, it is better to let Rusthon generate the extra functions, by giving the base class A as the type for g, the translator will know to regenerate the function for each subclass of A

def my_generic( g:A ) ->int:
	return g.method1()

Above is translated into 3 my_generic functions in c++, where g becomes: A, B, and C

c++ output

int my_generic(std::shared_ptr<A> g) {
	return g->method1();
}
int my_generic(std::shared_ptr<C> g) {
	return g->method1();
}
int my_generic(std::shared_ptr<B> g) {
	return g->method1();
}

https://github.com/rusthon/Rusthon/blob/master/regtests/c%2B%2B/generics_subclasses.py

multiple arguments

If your function takes multiple arguments that are subclasses, watch out, because this can lead to generating lots of code, because the translator generates each possible combination.

def my_generic2( g1:A, g2:A ) ->int:
	return g1.method1() * g2.method1()

c++ output

int my_generic2(std::shared_ptr<A> g1, std::shared_ptr<A> g2) {
	return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<C> g1, std::shared_ptr<C> g2) {
	return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<B> g1, std::shared_ptr<B> g2) {
	return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<B> g1, std::shared_ptr<C> g2) {
	return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<B> g1, std::shared_ptr<A> g2) {
	return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<C> g1, std::shared_ptr<A> g2) {
	return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<A> g1, std::shared_ptr<C> g2) {
	return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<C> g1, std::shared_ptr<B> g2) {
	return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<A> g1, std::shared_ptr<B> g2) {
	return (g1->method1() * g2->method1());
}

Sidebar

Clone this wiki locally