LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 02-04-2009, 03:34 AM   #1
unihiekka
Member
 
Registered: Aug 2005
Distribution: SuSE Linux / Scientific Linux / [K|X]ubuntu
Posts: 273

Rep: Reputation: 32
C++: different instances of a function template


Hi!

In my class template I have implemented several numerical integrators of different orders, i.e. I have a set of basic methods (M_1, ... M_N, say, where N > 1) that integrate a set of equations numerically for a given order (O_1, ... O_L, where L > 1 but is otherwise unrelated to N, all ints). I would like to implement it in a way that the user can provide the desired method an order, something along the lines of:

Code:
Problem.Integrate(Method, Order);
where Problem specifies the equations (does not really matter here anyway). How would I implement that in a fast and flexible way?

My old class used an if-then-else loop for both the methods and the orders, which seemed fairly stupid, because the methods and orders are supposed to be known at compile time, in which case it still ran through all M_N * O_L possibilities (at worst). So, if anyone has a good suggestion, I would be very happy to hear/read it.

Thanks!
 
Old 02-04-2009, 07:39 AM   #2
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,107

Rep: Reputation: 1114Reputation: 1114Reputation: 1114Reputation: 1114Reputation: 1114Reputation: 1114Reputation: 1114Reputation: 1114Reputation: 1114
You can use an int rather than a class as a template argument.

If appropriate, you can specialize on values of that int, which seems like what you would want to do for method and maybe for order.

If you don't also do some extra work, that would change your calling syntax:
Code:
Problem.Integrate(Method, Order);
might become
Code:
Problem.Integrate<Method, Order>();
You can add layers of code (usually with big switch statements) to convert from one calling syntax to the other. That might be worth it depending on where / how the calls are used.

It may seem the big switch statement would add the same run time overhead that you're trying to remove, and if you aren't careful it might.

When instantiating an inline function, where argument values are know at the call point, the compiler will bring that knowledge into the inline function. So many constructs that look like run time "if" or "switch" will actually be handled as compile time "if" or "switch". You can use this effect:
To write the layer that changes call syntax without the run time overhead it may seem to have.
To specialize less and write code templated on Method and/or Order that seems to do run time checks, but the compiler will effectively specialize.
To specialize only linearly on each of Method and Order, not combinatorialy on both (the compiler would instantiate combinatorialy specialized versions as used).

Exactly how to do any of that in your problem space depends on details you haven't provided. It may be fairly obvious or quite tricky. (But if you provided such details, that might also stop me from providing more specific help, because your problem space is quite close to something I work on professionally, subject to non disclosure).

Often, there is a big challenge in forcing the compiler to convert run time "if" operations into compile time "if" operations early enough in the optimization process to allow other optimizations that depend on that conversion. I have often used complicated extra layers of templates to convert what is logically a compile time "if" statement into a template instantiation, that the compiler is forced to resolve early in compile time, allowing subsequent optimization of the result.

gcc has some added features (not part of the C++ standard) for coding compile time "if" statements more directly. I think that is a better approach, but I can't use that myself because I must code for multiple compilers. Note I do NOT mean "#if". A preprocessor "if" is much too early, just as a run time "if" is much too late.

When I work on such problems, I generate asm output from the compiler and look at key points in the code to see whether the compiler really did convert the important tests from run time to compile time. Of course, if you don't know x86 assembler, doing that could be a lot harder.

Last edited by johnsfine; 02-04-2009 at 07:44 AM.
 
Old 02-05-2009, 06:28 AM   #3
unihiekka
Member
 
Registered: Aug 2005
Distribution: SuSE Linux / Scientific Linux / [K|X]ubuntu
Posts: 273

Original Poster
Rep: Reputation: 32
Thanks for the info!

I guess I'll try the TMP solution I found here (scroll down to "Switch statements"). The idea is basically the same, but I find this approach somewhat more appealing. I'll let you know if it works (or not) and if it's any good.
 
Old 02-05-2009, 01:50 PM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Something like this, maybe?
Code:
struct function {};

template <unsigned int> function integrate(function);


template <> function integrate <0> (function fFunction)
{ return fFunction; }

template <> function integrate <1> (function fFunction)
{
    function working(fFunction);
    /* integrate */;
    return working;
}

template <unsigned int Order> function integrate(function fFunction)
{ return ::integrate <1> ( ::integrate <Order - 1> (fFunction) ); }
ta0kira

PS This type of code structure requires the orders to be known at compilation time; Order must always be a constant expression. If you need to be able to vary the order for a given point in the code, you'll need to keep the order as an actual function argument and use a loop or recursion.

PPS Unless your functions can be integrated symbolically using only template semantics, you'll need to settle for at least some run-time recursion. In my opinion, unless you're dealing with very high orders, templatizing won't give you much of an advantage. Another solution, if you happen to know all combinations of order and function, is to precalculate all integrals and store them somewhere for later access. Unless you're talking about numerical integration, vs. antiderivatives.

Last edited by ta0kira; 02-05-2009 at 02:01 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
c++: template member function used in a different templated class matze Programming 5 04-10-2008 09:26 AM
c++ template function, expected constructor, destructor, or type conversion parv Programming 18 01-25-2008 02:54 PM
C++ Template For Generic Function - Is This Possible? taylor_venable Programming 6 06-05-2006 08:46 PM
function prototypes in template class' (c++) qwijibow Programming 4 12-13-2004 09:34 AM
problem in template function. compiles in vc++ not in gcc 3.0.4 cybercop12us Programming 4 12-12-2002 01:04 AM


All times are GMT -5. The time now is 01:50 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration