Jump to content
  • Advertisement
Sign in to follow this  
smc

Template function parameters

This topic is 3320 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have run across an issue where I have a template matrix class, and would like to pass this to a function without having to templatize the function. Here is an example
    template <unsigned S, typename T>
    struct Matrix {
    
        T mat[S][S] ;
        
        unsigned dim ;
        
        Matrix() : dim(S) {}
        
        T& operator()(unsigned i, unsigned j) { return mat[j] ; }
    };
    

    void invert(Matrix& m) {}

Essentially i am looking to pass a matrix to a function as if it were a standard class. However, I must make the function a template so I can inform the compiler of the type of matrix I am sending. My assumption is by doing this the code will be duplicated for each type of matrix I send it. This could possible cause quite a bit of code bloat. I see I could simply move the invert function into the matrix class. But I still believe for each matrix type the code would still be duplicated. Is there anyway to accomplish what I am trying to do?

Share this post


Link to post
Share on other sites
Advertisement
How would you know the dimensions of the Matrix inside of invert when it's not a template?

And how many different sizes do you really need?

Share this post


Link to post
Share on other sites

The dim member variable. And yes I do not need that many sizes. For my particular project I only need a 4x4. I just wanted to know if this was possible.

Share this post


Link to post
Share on other sites
You can create a base class with virtual functions that your Matrix class inherits from and then have functions use that.

Share this post


Link to post
Share on other sites
Quote:
Original post by smc

I see I could simply move the invert function into the matrix class. But I still believe for each matrix type the code would still be duplicated.


Templates are compile-time polymorphism, achieved through code generation for each instantiation. Each results in unique class with unique code path, completely unrelated to other instantiations of same template.

If this is not an option, matrix cannot be parametrized by S, and that parameter needs to be passed as regular value, and 'mat' allocated dynamically during run-time.

Quote:
This could possible cause quite a bit of code bloat.
Templates *are* bloat. Today's compilers have gotten really good at effectively eliminating it as a serious problem, but template instantiations result in more of similar, yet not duplicated, code.

Share this post


Link to post
Share on other sites
I suppose the actual work can be done by a function that doesn't need the size parameter.



namespace detail {
template <class T>
void invert(T* matrix_data, unsigned size)
{
//work here
}
}

template <class T, unsigned S>
void invert(Matrix<T, S>& m)
{
detail::invert(&m.mat[0][0], S);
}


Share this post


Link to post
Share on other sites
Quote:
Original post by visitor
I suppose the actual work can be done by a function that doesn't need the size parameter.

*** Source Snippet Removed ***


That still results in one instantiation of Matrix for each parameter pair, and one instance of invert.

Meanwhile, the only performance sensitive part - the calculation itself, will use non-constant values, which might (profiling!) result in slower run-time. The primary benefit of templated Matrix (unrolling, hard-coding of stack-allocated array or pre-calculating during compile time for compile-time known dimensions) will be lost. But since compiler will likely know that S is constant, it will probably inline entire //work into invert(), which will result in same outcome as if invert() were templated directly, the code is just less clear.

Profiling is required either way. But experience has shown that simply hard-coding some well-known matrices works in many cases, or generic, run-time constructed matrices are required anyway.

And code duplication in this case isn't necessarily problematic, even for larger numbers of matrices.

Share this post


Link to post
Share on other sites

SiCrane; This is a great solution. I will definitely have to play around with this approach. Come to think of it using templates types at the higher levels of inheritance is a nice way to create specialized types while keeping the majority of the code abstracted away from the specializations (in other words keeping it clean from type specifiers). I am not sure why I have not thought of this before. I really need to start playing around with the language.

Are there any good books/sites on class design patterns?

visitor; This is another possibility. It certainly would cut down on the code duplication size.


Thanks for the food.

Share this post


Link to post
Share on other sites
Original post by Antheus
Quote:
Original post by visitor

Meanwhile, the only performance sensitive part - the calculation itself, will use non-constant values, which might (profiling!) result in slower run-time. The primary benefit of templated Matrix (unrolling, hard-coding of stack-allocated array or pre-calculating during compile time for compile-time known dimensions) will be lost. But since compiler will likely know that S is constant, it will probably inline entire //work into invert(), which will result in same outcome as if invert() were templated directly, the code is just less clear.



This is interesting. I never considered using templates for performance optimizations. It definitely makes sense that the compiler could perform some serious optimizations on the code given the right information.

I just got knocked down to noob level again. I am glad I have the summer to work on some no deadline personal projects.

Share this post


Link to post
Share on other sites
Quote:
Original post by smc

This is interesting. I never considered using templates for performance optimizations. It definitely makes sense that the compiler could perform some serious optimizations on the code given the right information.


Well, you talked about code bloat, which is a compiler implementation detail, not a language issue, so I assumed other aspects matter too.

One of main reasons why code bloat is a problem (100Mb executable might be unwieldy, but is not problematic in itself, and would probably compress quite well) is the instruction cache problems, which usually results in slower running code, even though the operations are somewhat simpler. Even when compared to identical non-templated code, simply higher use of memory will cause slowdowns.

But as far as C++ language is concerned, code bloat is not really a factor, that is merely a practical consideration, for either performance, deployment or platform reasons.

I was once toying around with some template magic, and write a templated class that would generate instances for all 32-bit values. The resulting executable was several megabytes (I have no clue why it wasn't 16 gig, perhaps many ranges weren't used), and compilation took a minute or so (MVC2008), but it worked. It isn't something to do, I merely wanted to see if compiler could chew over this.

I think I was trying to parse user input into templated class using recursive parsing of digits, so that final template was result of multiple intermediate templates, but final version really did support entire 32-bit range.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!