Templated type-of object add_on

Started by
5 comments, last by WitchLord 9 years, 1 month ago

Until it's available as an engine feature, I've taken a stab at implementing the templated type-of object add_on as mentioned here. Note that this requires at least rev 2043 for an engine bugfix.

I register it into a custom namespace as follows:


engine->SetDefaultNamespace("myns");
RegisterScriptType(engine);
engine->SetDefaultNamespace("");

New Types

myns::typeid


class Foo {}
Foo foo;
 
void main()
{
    myns::typeid t = myns::typeof(foo);
 
    // implicitly convertible to a string
    print("type of t is: " + t);
 
    if ( t == myns::type<Foo>() )
        print("matches");
}

myns::type<T>


class Foo {}
 
void main()
{
    myns::type<Foo> typeOfFoo;
    myns::type<int> typeOfInt;
 
    // implicitly convertible to a string (or a myns::typeid for comparisons)
    print("Type of Foo is: " + typeOfFoo);
    print("Type of int is: " + typeOfInt);
}

New global functions

myns::typeid myns::typeof()


interface Base {}
class Derived : Base {}
 
Derived gDerived;
Base@ gBase = @gDerived;
 
void main()
{
    myns::type<Base>    typeOfBase;
    myns::type<Derived> typeOfDerived;
 
    print( myns::typeof(gDerived) == typeOfBase    ? "yes" : "no" );  // no
    print( myns::typeof(gDerived) == typeOfDerived ? "yes" : "no" );  // yes
    print( myns::typeof(gBase) == typeOfBase       ? "yes" : "no" );  // yes
    print( myns::typeof(gBase) == typeOfDerived    ? "yes" : "no" );  // no
 
    myns::mynsSprite@ anim = ...;
    if ( myns::typeof(anim) == myns::type<myns::Animation2d>() )
        print("It's an animation");
}

string myns::classname()



class Base
{
    Base() { print("constructing a: " + myns::classname(this)); }
}
 
class Derived : Base
{
    Derived() { print("constructing a: " + myns::classname(this)); }
}
 
void main()
{
    Derived derived;
    // "constructing a: Base"
    // "constructing a: Derived"
}
Advertisement

I just integrated this addon to my project, and tried to extend it by adding a method derivesFrom().

However, I came across an issue:


E: ../projects/samples/helloworld/HelloWorld.ac: (50, 33): No matching signatures to 'type::derivesFrom(type<Lol2>)'
I: ../projects/samples/helloworld/HelloWorld.ac: (50, 33): Candidates are:
I: ../projects/samples/helloworld/HelloWorld.ac: (50, 33): bool type::derivesFrom(const type<Lol>&in) const

The AS test code part:


        type<Lol> lolType;
        type<Lol2> lol2Type;
        print("Inherits: " + (lol2Type.derivesFrom(lolType)));

I registered derivesFrom this way:


r = engine->RegisterObjectMethod("type<T>", "bool derivesFrom(const type<T>&in) const", asMETHOD(CScriptType, DerivesFrom), asCALL_THISCALL); assert(r >= 0);

A strange thing is that opEquals is registered the exact same way, and if I do lol2Type.opEquals(lolType), the script compiles perfectly fine Oo

Note: I use AngelScript 2.30.0 WIP

----------------

I'm also wondering if it's possible to do something like:


auto t = typeof(instance); // What would be the STATIC type of "auto"?

However, it's not possible to implement since AS doesn't supports variable return types.

Maybe it could be fixed by making type<T> convertible to a non-template Type class, so we wouldn't need to know a type at advance (and that's the point of reflection, sometimes).


Type t = typeof(instance); // Type typeof(?)
Type t = type<MyClass>(); // type<T>() constructor, implicit cast to Type

(or maybe Type is just typeid needing same methods as type<T> ?)

-----------

Also, why this line?


    assert( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") == 0 );


Also, why this line?
assert( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") == 0 );

I didn't implement generic calling convention because I happen to not use it.

Can you try the latest version of the library?

Where can I find it? The only link I've seen so far are the files attached to your first post.

Here is my currently reflection stuff:

http://codepad.org/NkoNgRWI

http://codepad.org/eFOvrqPd (in end of this file you can find all API of reflection stuff)

Usage:


class A {}
class B : A { }

void main()
{
	// type can be retrieved by typeof call
	reflection::type t1 = reflection::typeof<A>();
	
	// also we can retrieve real type of class by passing reference as argument
	A@ aa = B();
	reflection::type t2 = reflection::typeof<A>(aa);
	t2 == reflection::typeof<B>(); // true
	
	// generic stuff
	reflection::type t = reflection::typeof<B>();
	t.derivesFrom(reflection::typeof<A>()); // true
	t.isEnum; // false
	t.isClass; // true
	t.propertiesCount; // 0
	t.nameWithoutNamespace; // B
	// etc
	
	// instantiation of derived types by base part
	A@ a = B();
	A@ b = clone(a);
	reflection::type tA = reflection::typeof<A>(a);
	reflection::type tB = reflection::typeof<A>(b);
	tA == tB; // true
}

A@ clone(A@ a)
{
	A@ newObj;
	reflection::typeof<A>(a).instantiate(@a, @newObj);
	return newObj; // here will be instance of class B, not A
} 

Maybe this helps to somebody.

If Andreas interested in this implementation, than I can format it to common AS code style (formatting, add generic calling convention) for future publication as add-on.

It looks quite nice. I'll consider including it as an add-on.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement