Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a variable as a template argument

Tags:

c++

templates

I am working with a library which exposes an interface to work with. One of the functions of this library is like this :

template <int a> void modify(){} 

I have to modify parameters from 1 to 10 i.e. call modify with with template arguments from 1 to 10. For that I wrote this code (a basic version of code, actual code is much larger).

for(int i=0; i<10; i++){     modify<i>(); } 

On compilation I receive the following error

error: 'i' cannot appear in constant-expression 

After going through some links on the internet, I came to know that I cannot pass any value as template argument which is not evaluated at compile time. My question are as follows: 1. Why can't compiler evaluate i at compile time? 2. Is there any other to achieve the objective I am trying to achieve without changing the API interface?


There is another thing I want to do. Call modify as modify where VAR is the output of some functional computation. How can I do that?

like image 963
gibraltar Avatar asked Jun 18 '12 11:06

gibraltar


2 Answers

What is the value of i (that is not a constant) at compile time? There is no way to answer unless executing the loop. But executing is not "compiling" Since there is no answer, the compiler cannot do that.

Templates are not algorithm to be executed, but macros to be expanded to produce code. What you can do is rely on specialization to implement iteration by recursion, like here:

#include <iostream>  template<int i> void modify() { std::cout << "modify<"<<i<<">"<< std::endl; }  template<int x, int to> struct static_for {     void operator()()      {  modify<x>();  static_for<x+1,to>()(); } };  template<int to> struct static_for<to,to> {     void operator()()      {} };   int main() {     static_for<0,10>()(); } 

Note that, by doing this, you are, in fact, instantiating 10 functions named modify<0> ... modify<9>, called respectively by static_for<0,10>::operator() ... static_for<9,10>::operator().

The iteration ends because static_for<10,10> will be instantiated from the specialization that takes two identical values, that does nothing.

like image 102
Emilio Garavaglia Avatar answered Oct 06 '22 20:10

Emilio Garavaglia


  1. "Why can't compiler evaluate i at compile time?"

    That would defeat the purpose of templates. Templates are there for the case where the source code looks the same for some set of cases, but the instructions the compiler needs to generate are different each time.

  2. "Is there any other to achieve the objective I am trying to achieve without changing the API interface?"

    Yes, look at Boost.MPL.

    However I suspect the right answer here is that you want to change the API. It depends on the internals of the modify function. I know you have it's source, because templates must be defined in headers. So have a look why it needs to know i at compile time and if it does not, it would be best to replace (or complement if you need to maintain backward compatibility) it with normal function with parameter.

like image 44
Jan Hudec Avatar answered Oct 06 '22 22:10

Jan Hudec