Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify template parameters at runtime

Tags:

c++

templates

Consider the following template class

class MyClassInterface { public:   virtual double foo(double) = 0; }  class MyClass<int P1, int P2, int P3> : public MyClassInterface { public:   double foo(double a) {     // complex computation dependent on P1, P2, P3   }   // more methods and fields (dependent on P1, P2, P3) } 

The template parameters P1, P2, P3 are in a restricted range like from 0 to some fixed value n fixed at compile time.

Now I would like to build a "factory" method like

MyClassInterface* Factor(int p1, int p2, int p3) {   return new MyClass<p1,p2,p3>(); // <- how to do this? } 

The question would be how to achieve the construction of the template class when template parameters are only known at runtime. And would the same be possible with template parameters having a very large domain (like a double)? Please consider also, if the possible solution is extendable to using more template parameters.

like image 957
Danvil Avatar asked May 20 '10 12:05

Danvil


People also ask

Are C++ templates runtime?

C++ does not support run-time resolution of template type arguments. To circumvent this restriction, we can instantiate a template for all possible combinations of type arguments at compile time and then select the proper instance at run time by evaluation of some provided conditions.

Are templates compile time or runtime?

All the template parameters are fixed+known at compile-time. If there are compiler errors due to template instantiation, they must be caught at compile-time!

What is correct for template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

Can template have default parameters?

You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };


1 Answers

Here's what you can do:

MyClassInterface* Factor(int p1, int p2, int p3) {   if (p1 == 0 && p2 == 0 && p3 == 0)     return new MyClass<0,0,0>();   if (p1 == 0 && p2 == 0 && p3 == 1)     return new MyClass<0,0,1>();   etc; } 

Note that this does not even remotely scale to floating point values. It scales only to a known list of discrete values.


I've also used this bit of code before to do some template automatic generation:

#include <boost/preprocessor.hpp>  #define RANGE ((0)(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)) #define MACRO(r, p) \     if (BOOST_PP_SEQ_ELEM(0, p) == var1 && BOOST_PP_SEQ_ELEM(1, p) == var2 && BOOST_PP_SEQ_ELEM(2, p) == var3 && BOOST_PP_SEQ_ELEM(3, p) == var4) \         actual_foo = foo<BOOST_PP_TUPLE_REM_CTOR(4, BOOST_PP_SEQ_TO_TUPLE(p))>; BOOST_PP_SEQ_FOR_EACH_PRODUCT(MACRO, RANGE RANGE RANGE RANGE) #undef MACRO #undef RANGE 

The compiler produces output that looks like this:

if (0 == var1 && 0 == var2 && 0 == var3 && 0 == var4) actual_foo = foo<0, 0, 0, 0>; if (0 == var1 && 0 == var2 && 0 == var3 && 1 == var4) actual_foo = foo<0, 0, 0, 1>; if (0 == var1 && 0 == var2 && 0 == var3 && 2 == var4) actual_foo = foo<0, 0, 0, 2>; if (0 == var1 && 0 == var2 && 0 == var3 && 3 == var4) actual_foo = foo<0, 0, 0, 3>; if (0 == var1 && 0 == var2 && 0 == var3 && 4 == var4) actual_foo = foo<0, 0, 0, 4>;  if (0 == var1 && 0 == var2 && 0 == var3 && 5 == var4) actual_foo = foo<0, 0, 0, 5>; if (0 == var1 && 0 == var2 && 0 == var3 && 6 == var4) actual_foo = foo<0, 0, 0, 6>; if (0 == var1 && 0 == var2 && 0 == var3 && 7 == var4) actual_foo = foo<0, 0, 0, 7>; if (0 == var1 && 0 == var2 && 0 == var3 && 8 == var4) actual_foo = foo<0, 0, 0, 8>; etc... 

Also, please note that with this method, with 4 variables, each ranging over 13 values, You would cause the compiler to instantiate 28561 copies of this function. If your n was 50, and you still had 4 options, you would have 6250000 functions instantiated. This can make for a SLOW compile.

like image 190
Bill Lynch Avatar answered Oct 02 '22 13:10

Bill Lynch