Advertisement

Help with template specialization class

Started by September 22, 2010 12:21 AM
0 comments, last by WitchLord 14 years, 2 months ago
[EDIT]: nvrmnd, got it working.

Okay, I edited this thinking I got it working but I was wrong. What I am doing is trying to get a multi-dimensional array class with template args working. It's only meant to be used right now by basic types handled with template specialization so it's not very robust, but I need a class that can handle up to three-dimensional arrays of different types.

What happens right now is I get a crash on
Array<int> arr;arr.resize( 64, 64, 64 ); //worksint temp = arr.at( 2 ); <--here


I looked at the array add_on and I think I do the reference counting the same, though I'd wager dollars to donuts that I am making some very simple mistake. Hopefully someone can spot it quickly. Here is the code:

namespace scriptarraytemplate{template<class T>class ScriptArray{public:	ScriptArray() : self(), ref_count(1), type(0) {}	ScriptArray( uint x ) : self(x), ref_count(1), type(0) {}	ScriptArray( uint y, uint x ) : self(y,x), ref_count(1), type(0) {}	ScriptArray( uint z, uint y, uint x ) : self(z,y,x), ref_count(1), type(0) {}	ScriptArray( const ScriptArray<T>& other ) : self(other.self), ref_count(1), type(0) {}	~ScriptArray()	{		if( type )			type->Release();	}	void AddTypeRef( asIObjectType *objType )	{		type = objType;		type->AddRef();	}	static ScriptArray<T>* ScriptArrayFactory()	{		ScriptArray<T> *a = new ScriptArray<T>();		return CheckScriptException( a );	}	static ScriptArray<T>* ScriptArrayFactory1( uint x )	{		ScriptArray<T> *a = new ScriptArray<T>( x );		return CheckScriptException( a );	}	static ScriptArray<T>* ScriptArrayFactory2( uint y, uint x )	{		ScriptArray<T> *a = new ScriptArray<T>( y, x );		return CheckScriptException( a );	}	static ScriptArray<T>* ScriptArrayFactory3( uint z, uint y, uint x )	{		ScriptArray<T> *a = new ScriptArray<T>( z, y, x );		return CheckScriptException( a );	}	static ScriptArray<T>* ScriptArrayFactoryCopy( const ScriptArray<T>& _Array )	{		ScriptArray<T> *a = new ScriptArray<T>( _Array );		return CheckScriptException( a );	}/////////////////////////////////////////////////////////////	static ScriptArray<T>* _ScriptArrayFactory( asIObjectType *objType )	{		ScriptArray<T> *a = new ScriptArray<T>();		a->AddTypeRef( objType );		return CheckScriptException( a );	}	static ScriptArray<T>* _ScriptArrayFactory1( asIObjectType *objType, uint x )	{		ScriptArray<T> *a = new ScriptArray<T>( x );		a->AddTypeRef( objType );		return CheckScriptException( a );	}	static ScriptArray<T>* _ScriptArrayFactory2( asIObjectType *objType, uint y, uint x )	{		ScriptArray<T> *a = new ScriptArray<T>( y, x );		a->AddTypeRef( objType );		return CheckScriptException( a );	}	static ScriptArray<T>* _ScriptArrayFactory3( asIObjectType *objType, uint z, uint y, uint x )	{		ScriptArray<T> *a = new ScriptArray<T>( z, y, x );		a->AddTypeRef( objType );		return CheckScriptException( a );	}	static ScriptArray<T>* _ScriptArrayFactoryCopy( asIObjectType *objType, const ScriptArray<T>& _Array )	{		ScriptArray<T> *a = new ScriptArray<T>( _Array );		a->AddTypeRef( objType );		return CheckScriptException( a );	}//////////////////////////////////////////////////////////////	static ScriptArray<T> *CheckScriptException( ScriptArray<T>* _Array )	{		// It's possible the constructor raised a script exception, in which case we 		// need to free the memory and return null instead, else we get a memory leak.		asIScriptContext *ctx = asGetActiveContext();		if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION )		{			delete _Array;			return 0;		}		return _Array;	}	ScriptArray<T>& AssignmentOperator( const ScriptArray<T>& rhs )	{		self = rhs.self;		return *this;	}	T* At1( uint x )	{		if( x >= self.Size() )		{			asIScriptContext* activeContext = asGetActiveContext();			if( activeContext )				activeContext->SetException("Array Index Out of Bounds.");			return 0;		}		return &self( x );	}	T* At2( uint y, uint x )	{		if( self.Offset(y, x) >= self.Size() )		{			asIScriptContext* activeContext = asGetActiveContext();			if( activeContext )				activeContext->SetException("Array Index Out of Bounds.");			return 0;		}		return &self( y, x );	}	T* At3( uint z, uint y, uint x )	{		if( self.Offset(z, y, x) >= self.Size() )		{			asIScriptContext* activeContext = asGetActiveContext();			if( activeContext )				activeContext->SetException("Array Index Out of Bounds.");			return 0;		}		return &self( z, y, x );	}	uint Size()	{		return self.Size();	}	void Resize1( uint x )	{		self.Resize(x);	}	void Resize2( uint y, uint x )	{		self.Resize(y, x);	}	void Resize3( uint z, uint y, uint x )	{		self.Resize(z, y, x);	}	bool Empty()	{		return self.Empty();	}	uint Offset1( uint x, Array<T>* self )	{		return x;	}	uint Offset2( uint y, uint x )	{		return self.Offset(y, x);	}	uint Offset3( uint z, uint y, uint x )	{		return self.Offset(z, y, x);	}	void Assign( uint begin, uint end, const T& value )	{		self.Assign( begin, end, value );	}	void AddRef()	{		++ref_count;	}	void Release()	{		if( --ref_count <= 0 )		{			delete this;		}	}protected:	Array<T> self;	int ref_count;	asIObjectType *type;};} //namespace scriptarraytemplatevoid ScriptingEngine::RegisterScriptArrayTemplateSpecializations(){	RegisterArrayTemplate<int>( "Array<T>", "T" );	RegisterArrayTemplateSpecialization<int>	( "Array<int>", "int" );	//RegisterArrayTemplateSpecialization<float>	( "Array<float>", "float" );	//RegisterArrayTemplateSpecialization<ubColor>	( "Array<Color>", "Color" );	//RegisterArrayTemplateSpecialization<Vector2>	( "Array<Vector2>", "Vector2" );}template <class T>void ScriptingEngine::RegisterArrayTemplateSpecialization( const std::string decl, const std::string type ){	int r(0);	using namespace scriptarraytemplate;	const std::string const_ref( (std::string("const ") + type) + " &in" );	// register the array type	r = engine->RegisterObjectType( decl.c_str(), 0, asOBJ_REF ); assert( r >= 0 );	// constructors	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, 		( decl + " @f()" ).c_str(), 		asFUNCTION(ScriptArray<T>::ScriptArrayFactory), asCALL_CDECL ); assert( r >= 0 );		r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY,		(((decl + " @f(") + const_ref) + ")" ).c_str(),		asFUNCTION(ScriptArray<T>::ScriptArrayFactory1), asCALL_CDECL ); assert( r >= 0 );		r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY,		(((((decl + " @f(") + const_ref) + "," ) + const_ref ) + ")" ).c_str(),		asFUNCTION(ScriptArray<T>::ScriptArrayFactory2), asCALL_CDECL ); assert( r >= 0 );	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY,		(((((((decl + " @f(") + const_ref) + "," ) + const_ref ) + "," ) + const_ref ) + ")" ).c_str(),		asFUNCTION(ScriptArray<T>::ScriptArrayFactory3), asCALL_CDECL ); assert( r >= 0 );	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY,		(((decl + " @f(const ") + decl) + " &in)" ).c_str(),		asFUNCTION(ScriptArray<T>::ScriptArrayFactoryCopy), asCALL_CDECL ); assert( r >= 0 );	// index methods	r = engine->RegisterObjectMethod( decl.c_str(),		( type + "& at(uint)" ).c_str(),		asMETHOD(ScriptArray<T>, At1), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		( type + "& at(uint, uint)" ).c_str(),		asMETHOD(ScriptArray<T>, At2), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		( type + "& at(uint, uint, uint)" ).c_str(),		asMETHOD(ScriptArray<T>, At3), asCALL_THISCALL ); assert( r >= 0 );	// resize methods	r = engine->RegisterObjectMethod( decl.c_str(),		"void resize(uint)",		asMETHOD(ScriptArray<T>, Resize1), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"void resize(uint, uint)",		asMETHOD(ScriptArray<T>, Resize2), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"void resize(uint, uint, uint)",		asMETHOD(ScriptArray<T>, Resize3), asCALL_THISCALL ); assert( r >= 0 );	// operators	r = engine->RegisterObjectMethod( decl.c_str(),		( decl + "& opAssign(const " + type + " &in)" ).c_str(),		asMETHOD(ScriptArray<T>, AssignmentOperator), asCALL_THISCALL ); assert( r >= 0 );	// methods	r = engine->RegisterObjectMethod( decl.c_str(),		"bool empty() const",		asMETHOD(ScriptArray<T>, Empty), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"uint size() const",		asMETHOD(ScriptArray<T>, Size), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"uint offset(uint)",		asMETHOD(ScriptArray<T>, Offset1), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"uint offset(uint, uint)",		asMETHOD(ScriptArray<T>, Offset2), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"uint offset(uint, uint, uint)",		asMETHOD(ScriptArray<T>, Offset3), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		(( std::string( "void assign(uint, uint, " ) + const_ref ) + ")" ).c_str(),		asMETHOD(ScriptArray<T>, Assign), asCALL_THISCALL ); assert( r >= 0 );	// memory management	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_ADDREF, "void f()", asMETHOD(ScriptArray<T>, AddRef), asCALL_THISCALL); assert( r >= 0 );	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_RELEASE, "void f()", asMETHOD(ScriptArray<T>, Release), asCALL_THISCALL); assert( r >= 0 );	}template <class T>void ScriptingEngine::RegisterArrayTemplate( const std::string decl, const std::string type ){	int r(0);	using namespace scriptarraytemplate;	const std::string const_ref( (std::string("const ") + type) + " &in" );	// register the array type	r = engine->RegisterObjectType( "Array<class T>", 0, asOBJ_REF | asOBJ_TEMPLATE ); assert( r >= 0 );	// constructors	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, 		( decl + " @f(int &in)" ).c_str(), 		asFUNCTION(ScriptArray<T>::_ScriptArrayFactory), asCALL_CDECL ); assert( r >= 0 );	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY,		(((decl + " @f(int &in, ") + const_ref) + ")" ).c_str(),		asFUNCTION(ScriptArray<T>::_ScriptArrayFactory1), asCALL_CDECL ); assert( r >= 0 );	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY,		(((((decl + " @f(int &in, ") + const_ref) + "," ) + const_ref ) + ")" ).c_str(),		asFUNCTION(ScriptArray<T>::_ScriptArrayFactory2), asCALL_CDECL ); assert( r >= 0 );	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY,		(((((((decl + " @f(int &in, ") + const_ref) + "," ) + const_ref ) + "," ) + const_ref ) + ")" ).c_str(),		asFUNCTION(ScriptArray<T>::_ScriptArrayFactory3), asCALL_CDECL ); assert( r >= 0 );	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY,		(((decl + " @f(int &in, const ") + decl) + " &in)" ).c_str(),		asFUNCTION(ScriptArray<T>::_ScriptArrayFactoryCopy), asCALL_CDECL ); assert( r >= 0 );	// index methods	r = engine->RegisterObjectMethod( decl.c_str(),		( type + "& at(uint)" ).c_str(),		asMETHOD(ScriptArray<T>, At1), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		( type + "& at(uint, uint)" ).c_str(),		asMETHOD(ScriptArray<T>, At2), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		( type + "& at(uint, uint, uint)" ).c_str(),		asMETHOD(ScriptArray<T>, At3), asCALL_THISCALL ); assert( r >= 0 );	// resize methods	r = engine->RegisterObjectMethod( decl.c_str(),		"void resize(uint)",		asMETHOD(ScriptArray<T>, Resize1), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"void resize(uint, uint)",		asMETHOD(ScriptArray<T>, Resize2), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"void resize(uint, uint, uint)",		asMETHOD(ScriptArray<T>, Resize3), asCALL_THISCALL ); assert( r >= 0 );	// operators	r = engine->RegisterObjectMethod( decl.c_str(),		( decl + "& opAssign(const " + type + " &in)" ).c_str(),		asMETHOD(ScriptArray<T>, AssignmentOperator), asCALL_THISCALL ); assert( r >= 0 );	// methods	r = engine->RegisterObjectMethod( decl.c_str(),		"bool empty() const",		asMETHOD(ScriptArray<T>, Empty), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"uint size() const",		asMETHOD(ScriptArray<T>, Size), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"uint offset(uint)",		asMETHOD(ScriptArray<T>, Offset1), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"uint offset(uint, uint)",		asMETHOD(ScriptArray<T>, Offset2), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		"uint offset(uint, uint, uint)",		asMETHOD(ScriptArray<T>, Offset3), asCALL_THISCALL ); assert( r >= 0 );	r = engine->RegisterObjectMethod( decl.c_str(),		(( std::string( "void assign(uint, uint, " ) + const_ref ) + ")" ).c_str(),		asMETHOD(ScriptArray<T>, Assign), asCALL_THISCALL ); assert( r >= 0 );	// memory management	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_ADDREF, "void f()", asMETHOD(ScriptArray<T>, AddRef), asCALL_THISCALL); assert( r >= 0 );	r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_RELEASE, "void f()", asMETHOD(ScriptArray<T>, Release), asCALL_THISCALL); assert( r >= 0 );	}



Just curious; Any plans to allow a class to register their own index operator? Like: "T& uint[][][] f()" or something which might translate to "T& f(uint,uint,uint)"? It's a quick mock-up but that's the idea. Right now index ops can take only a single value.

[Edited by - arpeggiodragon on September 22, 2010 6:49:35 PM]
I've been playing with the thought of having index operators with multiple arguments, and also different arguments, e.g. strings. But nothing is fixed yet.

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