1

I have got template function with function pointer as a template parameter. When I use global function pointer as template parameters everything works fine. When I try to define function locally using lambda(without capturing) problems arise. Here is minimal code:

#include <vector>
#include <iostream>

template<double (*f)(double, double)>
std::vector<double> calculate(std::vector<double>& x, std::vector<double>& y){
    std::vector<double> z(x.size());
    std::transform(x.begin(),x.end(),y.begin(),z.begin(),f);
    return z;
}

double calc(double n, double k){
    return n*n+k*k;
}

int main(int argc, char *argv[])
{
    double (*fun)(double,double) = [](double n, double k){return n*n+k*k;};
    std::vector<double> x(5,3);
    std::vector<double> y(5,4);
    std::vector<double> z1 = calculate<&calc>(x,y);//it works fine
    std::vector<double> z2 = calculate<fun>(x,y);//this line gives a bunch of errors

    for(int i=0;i<z1.size();i++){
        std::cout<<z1[i]<<" ";
    }
    for(int i=0;i<z2.size();i++){
        std::cout<<z2[i]<<" ";
    }
    return 0;
}

Here is errors:

  1. the value of 'fun' is not usable in a constant expression
  2. no matching function for call to 'calculate(std::vector<double>&, std::vector<double>&)
  3. 'fun' is not a valid template argument for type 'double (*)(double, double)'
  4. it must be the address of a function with external linkage
4

2 Answers 2

2

calc is a constant and can be used as a template parameter, while instead fun is a variable and therefore cannot.

Unfortunately you cannot pass a lambda directly as a template parameter just because you cannot (the standard says you cannot)... so the following is not going to work:

calculate<[](double n, double k){ return n*n+k*k; }>(x, y);

In you specific case however it's not clear why the function is a template parameter and not just a parameter... (in that case passing fun would work fine).

Sign up to request clarification or add additional context in comments.

Comments

0

You can only pass pointer to functions as template arguments if they're constexpr. In this case however:

double (*fun)(double,double) = [](double n, double k){return n*n+k*k;};

fun is not, thus you cannot pass it as a template argument.

In simple words fun is runtime variable and you cannot pass a runtime variable as template argument.

3 Comments

function calc is not constexpr.Why can I use it as template parameter?
And unfortunately you cannot pass a lambda either with calculate<[](double n, double k){ return n*n+k*k; }>(x, y) even if that would be constant (just because you cannot).
@lnk I'm not talking about constexpr functions. fun is not a constant expression.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.