T T
T T

Reputation: 154

How to dynamically add template parameter

I'm new to C++ and have got stuck with an implementation. So my problem is as below:

I have interface classes, where the only difference in the classes is the no. of parameters one of its function has.

For Example:

class foo3()
{
    private:
       function3(a,b,c) {}
};

class foo5()
{
    private:
       function5(a,b,c,d,e) {}
};

To generalize these and use them without knowing their inner functionality, I have created a template class fooN and used template specialization, thus based on template parameter(int N) I can choose correct class object and do some processing.

Now I have algorithm where I'm creating an object of fooN template

class algo {
     public:
         fooN<5> fooObj;
     private:
 }

Is it possible to dynamically assign this template parameter(5) at run-time, or is there a work-around?

Currently I'm using CMake to statically set the template parameter.

Upvotes: 0

Views: 1016

Answers (2)

Useless
Useless

Reputation: 67743

Is it possible to dynamically assign this template parameter(5) at run-time

Absolutely not. All template instantiation happens at compile time.

or is there a work-around?

Maybe.

You can certainly instantiate fooN for a bunch of different values, and choose between them at runtime. The simplest way is something like this

int algo(int n)
{
  switch(n) {
  case 3: return algoImpl<3>();
  case 5: return algoImpl<5>();
  default: return -1;
  }
}

although you obviously need to get your parameters from somewhere. You can reasonably have each algoImpl<N> take a (runtime) vector of argument values, convert it into a tuple, and use std::apply to invoke your underlying function.

Currently I'm using CMake

Commiserations.

... to statically set the template parameter.

Eww. Storing bits of your type system in a build configuration file feels a bit hairy. What does your build system know about the correct value of N that your code doesn't?

Upvotes: 2

meetaig
meetaig

Reputation: 915

Unfortunately this is not possible. Template parameters need to be known at compile time

When the compiler encounters this call to a template function, it uses the template to automatically generate a function replacing each appearance of myType by the type passed as the actual template parameter (int in this case) and then calls it. This process is automatically performed by the compiler and is invisible to the programmer.

source

Meaning all the values the template can be used with need to be known at compile time.

What you can do is the following

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;
}

But as you want an arbitrary number N, I assume this is not a solution that is feasible for you. You can try to add a preprocessor macro to generate the function for arbitrary values of N, but honestly, I wouldn't do that. It will make you executables very large and add a lot of time to your compile time.

You can maybe find a solution that is similar to what you're trying to do with initializer lists. This would let you do something like

my_type Var = {1, 2, 3, 4, 5, 6, ..., N};

You can use such a list as the parameter of a function.

Hope that helped you with what you're trying to achieve!

Upvotes: 0

Related Questions