Archived

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

kamrann

Why can't I do this with templates?

Recommended Posts

I posted a while ago about using templates for a generic matrix class. I'm defining it like: template <> class CMatrix { ... }; I want to be able to specialize certain functions for certain combinations of R and C (rows/columns). For example, in my Determinant function, if R == 2 then I just return the value calculated from the simple formula for determinant of a 2x2 matrix. Otherwise, its calculated recursively, which involves creating matrix objects like: CMatrix minor ... Problem is, if I just use a normal if, the compiler keeps trying to compile the template class for all sizes down to 0x0, at which point I get 0-sized array error and other problems. So I just thought I could do: #if R == 3 define function in one way #else otherwise define recursively #endif inside the function body. Being able to do this would be real useful for other things too, but it wont let me do it, since I cant use R in that way - #ifdef R evaluates to false. I dont see why the compiler shouldn't be able to use template arguments in this way. Anyway, does anyone know of any other way that I could achieve the same thing? Thanks Cameron Edited by - kamrann on October 21, 2001 3:37:31 PM

Share this post


Link to post
Share on other sites
The way to do this is to terminate the recursion with a partially specialized template class:

template <int R, int C, typename T = float>
class CMatrix
{
    /* code for NxN matrix, using other matrix classes recursively as needed */
};

template <typename T>
class CMatrix<3,3,T>
{
    /* code for 3x3 matrix, ends the recursion */
};

If you're using Visual C++, be advised that the support for templates is spotty at best. The above code (correct according to the Standard) won't compile with VC++, at least not version 6.



Edited by - spock on October 21, 2001 11:39:14 AM

Share this post


Link to post
Share on other sites
When you say that it won''t compile with VC++6, do you mean the syntax is different, or that VC++6 simply can''t do it at all?

Also, by partially specializing, do I have to redefine the whole class? In other words, if most of the class member functions are going to be the same for all values of R and C, is there some way of specializing just certain functions for certain R and C combinations?

thanks
Cameron

Share this post


Link to post
Share on other sites
It's been a while since I used the Visual C++ compiler, but as far as I can remember VC++ 6 don't support partial specialization, at least not in any meaningful way. Sometimes it's possible to work around these limitations by using member templates etc, but it's a pain and you keep running into ICEs (Internal Compiler Errors).

From what I've heard, the support for Standard C++ won't be very good in VC++ 7, either. I switched to Intels VC++-compatible compiler some time ago and haven't looked back since.

The partial specialization is a distinct class template, so yes, it does need to be completely defined. But you won't need to define any members you don't use in the recursion, because these will never be called anyway.



Edited by - spock on October 21, 2001 1:09:18 PM

Share this post


Link to post
Share on other sites
That is not a particularly efficient way of calculating the determinant. IIRC, the efficiency of this algorithm is O(n!). Doing row operations until you have a triangular matrix and summing the elements along the main diagonal will be a hell of a lot faster.

This following example generates an upper triangular matrix. Calculating the determinant by summing the elements along the main diagonal should then be trivial(beware, this is hardly optimized code).
http://sourcepost.sytes.net/source/sourceview.aspx?source_id=344

"A society without religion is like a crazed psychopath without a loaded .45"

Share this post


Link to post
Share on other sites
Thanks for the replies.

I'm still unclear on how this template specialization works. Theres not much detail on templates in the VC++6 help files, probably because the compiler can't handle them.

If I have

// sorry, all angled brackets replaced by parentheses cos
// this board keeps ripping them off my posts

template (int R, int C, typename T)
class MyClass
{
...
};


and then

template (typename T)
class MyClass(3, 3, T)
{
...
};

then am I right in assuming these class templates are really independent - the second part is just a way of providing special behaviour for a certain parameter combination?
So then if I define lots of methods in MyClass, and just one of those in MyClass(3, 3, T), and then instantiate:
MyClass(3, 3, float) obj; // or MyClass(float) ??

then obj won't have all the methods defined in the general
MyClass template?

This is all getting too confusing. Any pointers to articles about more advanced use of templates would be very helpful.

Thanks all
Cameron

Edited by - kamrann on October 21, 2001 3:52:24 PM

Share this post


Link to post
Share on other sites
quote:
Original post by kamrann
if I define lots of methods in MyClass, and just one of those in MyClass(3, 3, T), and then instantiate:
MyClass(3, 3, float) obj; // or MyClass(float) ??

then obj won''t have all the methods defined in the general
MyClass template?



Yes, that''s correct. The two classes MyClass<3,3,float> and MyClass<4,4,float> (for example) does not necessarily have the same members.

quote:

This is all getting too confusing. Any pointers to articles about more advanced use of templates would be very helpful.



Sorry, I haven''t got any better pointers than Stroustrups books at the moment. I''d like to encourage use of templates - it''s an extremely powerful concept once you''ve wrapped your head around it. Perhaps I should write such an article...

Share this post


Link to post
Share on other sites