Archived

This topic is now archived and is closed to further replies.

joanusdmentia

template instantiation

Recommended Posts

I was wondering if anyone out there knows of a way to get templates to get instantiated for only a select group of types. That's probably not the best description, so here's an example. I've been implementing a temporary-free templated vector class (anyone who reads flipcode as well will recognize it from this tutorial: http://www.flipcode.com/tutorials/tut_fastmath.shtml). Anyway, say I have an operator overloaded as follows:
template < class TL, class TR >
inline const Expr2 < const TL, const TR, Add >
operator+(const TL &L, const TR &R)
{
	return Expr2 < const TL, const TR, Add >(L,R);			
}
 
is there any way to tell the compiler that we only want this operator instantiated only for certain types of TL and TR? At the moment it's got obvious problems being instantiated for any + operation, but if there isn't a way to do this i'm looking at 16 different copies of exactly the same code, per operator, with the only difference being the types of TL and TR Joanus D'Mentia --------------- The three phases of me... The twit, the tool and the lonely fool [edited by - joanusdmentia on November 1, 2002 9:04:07 PM] [edited by - joanusdmentia on November 1, 2002 9:05:10 PM]

Share this post


Link to post
Share on other sites
The shorter answer would be what types I _do_ want it to work with. I only want it to work with scalars (e.g. float), Vector::Base (which as the name implies is a base class for all vectors) and Vector::Expr? (where ? = 1 or 2, these are classes that represent an expression).

When I first implemented it I didn''t even think about what affect it would have with other types, and my test environment really only did vector math so I didn''t run into any problems. When I moved it into my project though I got all sorts of errors, mostly stemming from stl iterators that were using the vectors overloaded operators.

Share this post


Link to post
Share on other sites
If you are overriding the global + operator, I do not think there is a way to stop all types from being overridden the way you have it described.

However, putting the + operator within the vector class will do what you want, it will still be called when the vector class is used, but not for anything else.

So, for example:

  
class Vector {
inline Vector operator+(const Vector &value) const
{
Vector tmp;
tmp.x = x + value.x; // etc...

return tmp;
}
};

Share this post


Link to post
Share on other sites
I''m writing this vector code as well, with ET and loop unrolling...
well, I''m going to be using this other guys code, but add loop unrolling, concept checks, etc, etc and then incorprate that in to libGDN.
but back to the question.
yes, you would put it into the vector class. that way only vectors use the + operator.

also. look into Boost concept checks for this kind of template metaprogramming. you can force compile time errors if the user attempts to instanitate vector classes with types that don''t support what you need, ie, +, -, *, copyable..


-----------------------------
Gamedev for learning.
libGDN for putting it all together.

Share this post


Link to post
Share on other sites
ok, but the problem with that is it would no longer apply to the Expr? classes, so you wouldn''t be able to do something like this:

v4 = v1+v2+v3;

v1+v2 would evaluate to an Expr2 class, and you''d then need a seperate Expr2::operator+. Is there no way around this or am I just being really simple and looking over something?

Share this post


Link to post
Share on other sites
edit:
once again, a non-working 'solution'. When you're overloading operator+(), this scheme won't work. It just assures that some template function can be called with only certain parameters.

/* //I commented this away
This works (kinda variation of BOOST_STATIC_ASSERT):

    
template <typename T> struct PLUS_OK_TYPE;
template <> struct PLUS_OK_TYPE<float>{};
template <> struct PLUS_OK_TYPE<double>{};

template <typename TL, typename TR>
TL plus(TL a, TR b) {
sizeof(PLUS_OK_TYPE<TL>);
sizeof(PLUS_OK_TYPE<TR>);
return a + b;
}

Now if you call plus(), and the arguments don't have a specialization of PLUS_OK_TYPE, the linker will complain. I take a sizeof() because it'll be optimized away.

But it looks dirty...
*/


[edited by - civguy on November 2, 2002 8:37:10 AM]

Share this post


Link to post
Share on other sites
KEWL!!!

that is EXACTLY what I was after!! I can't see why you're operator+ wouldn't have worked though, after trying your approach it worked fine. i think you would have run into trouble because you were using built-in types. If I do something like


  
struct Test1 { int a,b; };
struct Test2 { int a,b; };
struct Test3 { int a,b; };

template<class T> struct Test_ValidParam;
template<> struct Test_ValidParam<Test1>{};
template<> struct Test_ValidParam<Test2>{};

template<class TL, class TR>
int operator+(const TL &L, const TR &R)
{
sizeof(Test_ValidParam<TL>);
sizeof(Test_ValidParam<tr>);
return L.a + R.b;
}

void func(void)
{
Test1 t1;
Test2 t2;
Test3 t3;

int a = t1+t2; // OK

int b = t1+t3; // undefined type Test_ValidParam<Test3>

}


Thanks! My wrapper class did work, but the problem was I couldn't have scalars on the left hand side. Not a big deal, i know....


[edited by - joanusdmentia on November 2, 2002 8:56:27 PM]

Share this post


Link to post
Share on other sites
damn it, now for my next problem:

is something like this possible?


    
template<class T> struct VECTOR_EXPRESSION_TYPE;

template<> template<unsigned int n, class _T>
struct VECTOR_EXPRESSION_TYPE< Base<n,T> >{};

template<> template<class TR, class TE>
struct VECTOR_EXPRESSION_TYPE< Expr1<TR,TE> >{};

template<> template<class TL, class TR, class TE>
struct VECTOR_EXPRESSION_TYPE< Expr2<TL,TR,TE> >{};


where Base, Expr1<tr,TE>, Expr2 are defined early.
.Net doesn't like it, that's for sure.

[edited by - joanusdmentia on November 2, 2002 9:10:35 PM]

Share this post


Link to post
Share on other sites