Passing a variable as a template argument

template argument list must match the parameter list
template template parameter
template argument for template type parameter must be a type
c++ function as template parameter
c++ templates
template argument deduction
non-type template parameter
template template parameter policy

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?


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.

passing a variable as template argument, I don't think you can do like that. n is known at compile time, but it is not known as a template argument. Since you need n in your Tree constructor, you could  The deduction is performed as if by deducing the type of the variable x in the invented declaration T x = template-argument;, where T is the declared type of the template parameter. If the deduced type is not permitted for a non-type template parameter, the program is ill-formed. template<auto n > struct B { /*


Since you asked for an answer using Boost.MPL:

#include <boost/mpl/for_each.hpp>
#include <boost/mpl/range_c.hpp>

#include <iostream>

template <int N>
void modify()
{
    std::cout << N << '\n';
}

// You need to wrap your function template in a non-template functor
struct modify_t
{
    template <typename N>
    void operator()(N)
    {
        modify<N::value>();
    }
};

int main()
{
    namespace mpl = boost::mpl;

    mpl::for_each< mpl::range_c<int,0,10> >( modify_t() ); // prints 0 to 9
}

Template parameters and template arguments, The declared variable name becomes a template name. parameter-list, -, a non-​empty comma-separated list of the template parameters, each of which is either  You can actually pass the variable to the next template scope by set the custom query variable again, cause load_template will extract new arguments and your first set_query_var will be at no existance. Just do it in the SAME scope where the load_template is in use. A smart way to do this “passing” is another thread.


  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.

Variable template(since C++14), When instantiating a class template, we have to pass in the types explictly new variable, so there is no need to keep const -ness, for example. Passing a variable as a template argument. Ask Question Asked 8 years ago. Active 1 year, 2 months ago. Viewed 23k times 25. 7. I am working with a library which


Without using struct or Boost it can also be done :

#include <iostream>
#include <utility>

template <int a>
void modify()
{
    std::cout<<a<<",";
}

template<int i,size_t... t>
constexpr inline void CT_for_impl(std::integer_sequence<size_t,t...>)
{
    bool kai[]= { (modify<i+t>(), false)...};
}

template<int i,int n>
constexpr inline void CT_for()
{
    CT_for_impl<i>(std::make_index_sequence<n-i+1>());
}

int main()
{
    CT_for<-5,5>();
    return 0;
}

Function templates, 2) A non-type template parameter with an optional name and a default value with linkage (or constant expressions that evaluate to null pointer values). Default template argument of a variable template is implicitly instantiated when the variable template is used in the context that requires the value of the argument. Notes. Until variable templates were introduced in C++14, parametrized variables were typically implemented as either static data members of class templates or as constexpr


solution to error: 'i' cannot appear in constant-expression for the above problem

To read about constexpr click this link

#include <iostream>
using namespace std;

template <typename T>
void modify(T a)
{
    cout<<a<<endl;  //to check if its working 
}


//func converts int a into const int a
constexpr int func(int a)
{
    return a;
}

int main(){
    for(int i=0; i<10; i++){
        modify(func(i));//here passing func(i) returned value which can be used as template argument now as it is converted to constexpr    
}
    return 0;
}

Template parameters and template arguments, The resulting values of non-type template arguments within a template argument list form part of the template class type. If two template class names have the  Variadic templates. One of the new features of C++11 is variadic templates.Finally, there's a way to write functions that take an arbitrary number of arguments in a type-safe way and have all the argument handling logic resolved at compile-time, rather than run-time.


Template non-type arguments (C++ only), A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values  Template non-type arguments (C++ only) A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.


Templates - C++ Tutorials, In this case, by using int as template argument in the call, the compiler template argument needs to be a constant expression (it cannot be passed a variable). Template variables silently coalesce to empty strings when a replacement value isn't found. Template expressions, unlike macro and runtime expressions, can appear as either keys (left side) or values (right side). The following is valid: $ { { variables.key }} : $ { { variables.value }}.


Overloads and templates - C++ Tutorials, With C++11 and C++14 you can use it to automatically deduce variables or even return types, plus there are also generic lambdas. Now you can also use it for  Within a template expression, you have access to the parameters context which contains the values of parameters passed in. Additionally, you have access to the variables context which contains all the variables specified in the YAML file plus the system variables. Importantly, it doesn't have runtime variables such as those stored on the pipeline or given when you start a run.