I'm trying to wrap my mind around the interaction of C++ lambda expressions and templates.
This code works as I expect:
#include <iostream>
int bar (int x, int (* f) (int))
{
return f (x);
}
double bar (double x, double (* f) (double))
{
return f (x);
}
int main ()
{
std::cout << bar (16, [] (int x) -> int { return x * x; }) << std::endl;
std::cout << bar (1.2, [] (double x) -> double { return x * x; }) << std::endl;
return 0;
}
So does this:
#include <iostream>
#include <functional>
int bar (int x, std::function<int (int)> f)
{
return f (x);
}
double bar (double x, std::function<double (double)> f)
{
return f (x);
}
int main ()
{
std::cout << bar (16, [] (int x) -> int { return x * x; }) << std::endl;
std::cout << bar (1.2, [] (double x) -> double { return x * x; }) << std::endl;
return 0;
}
So far, so good. But neither of the following examples compile:
#include <iostream>
template <typename T>
T bar (T x, T (* f) (T))
{
return f (x);
}
int main ()
{
std::cout << bar (16, [] (int x) -> int { return x * x; }) << std::endl;
std::cout << bar (1.2, [] (double x) -> double { return x * x; }) << std::endl;
return 0;
}
and
#include <iostream>
#include <functional>
template <typename T>
T bar (T x, std::function <T (T)> f)
{
return f (x);
}
int main ()
{
std::cout << bar (16, [] (int x) -> int { return x * x; }) << std::endl;
std::cout << bar (1.2, [] (double x) -> double { return x * x; }) << std::endl;
return 0;
}
GCC version 8.3.0 (with -std=c++17) gives an error message:
no matching function for call to 'bar(int, main()::<lambda(int)>' (and
another for the "double" version) and "template argument
deduction/substitution failed: main()::<lambda(int)> is not derived
from std::function<T(T)>" (for the second failing example).
However, this assignment works:
std::function<int (int)> f = [] (int x) -> int { return x * x; };
Could anyone please shed light for me? (Obviously, this isn't practical code. This is just an attempt to learn.)