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
lnk
  • 593
  • 2
  • 11
  • 27
  • Lambas have an unspecified type; either use `auto` or `std::function` to store them. – Jonathan Potter Nov 19 '15 at 22:20
  • AFAICT, this is a duplicate of http://stackoverflow.com/questions/6420085/is-constexpr-supported-with-lambda-functions-expressions. The 'fun' is a variable and as such cannot be used as a template parameter. – Mats Kindahl Nov 19 '15 at 22:20
  • @MatsKindahl Seems closer to https://stackoverflow.com/questions/5849059/lambda-expressions-as-class-template-parameters?rq=1 ? – Jonathan Potter Nov 19 '15 at 22:21
  • Possible duplicate of [Passing lambda as template parameter to templated by function-pointer function](http://stackoverflow.com/questions/31031999/passing-lambda-as-template-parameter-to-templated-by-function-pointer-function) – 101010 Nov 19 '15 at 22:38

2 Answers2

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).

6502
  • 112,025
  • 15
  • 165
  • 265
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.

101010
  • 41,839
  • 11
  • 94
  • 168
  • function `calc` is not `constexpr`.Why can I use it as template parameter? – lnk Nov 19 '15 at 22:28
  • 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). – 6502 Nov 19 '15 at 22:29
  • @lnk I'm not talking about `constexpr` functions. `fun` is not a constant expression. – 101010 Nov 19 '15 at 22:32