I'm working on this exercise 18.7 in C++ Primer Plus (6th edition):
and the code I gave was like this, using the lambda expression as required:
#include <iostream>
#include <array>
#include <algorithm>
const int Size = 5;
template <typename T>
void sum(std::array<double, Size> a, T& fp);
int main()
{
double total = 0.0;
std::array<double, Size> temp_c = {32.1, 34.3, 37.8, 35.2, 34.7};
sum(temp_c, [&total](double w){ total += w; });
std::cout << "total: " << total << std::endl;
std::cin.get();
return 0;
}
template <typename T>
void sum(std::array<double, Size> a, T& fp)
{
for (auto pt = a.begin(); pt != a.end(); ++pt)
fp(*pt);
}
After I compiled it in VSCode, an error came out:
cannot bind non-const lvalue reference of type 'main(int, char**)::<lambda(double)>&' to an rvalue of type 'main(int, char**)::<lambda(double)>'
. I also checked the official answer, which is virtually the same as my code and gave the same error while being compiled. I think this is because the void
type function doesn't match the T&
type called in template function sum
, but how to modify the code while keeping the original sum()
function unchanged as required in the problem? And I'm also confused why there's a lvalue & rvalue problem here.
Thanks in advance for any answers & explanations.
By defining your lambda inline you have made it a temporary, an r-value. This means that because the template takes the function pointer as a non-const ref (ugh!), there's no conversion - the rvalue cannot be bound to an l-value parameter, so it does not compile. If you lift the lambda out into its own variable, it works:
#include <iostream>
#include <array>
#include <algorithm>
const int Size = 5;
template <typename T>
void sum(std::array<double, Size> a, T& fp);
int main()
{
double total = 0.0;
std::array<double, Size> temp_c = {32.1, 34.3, 37.8, 35.2, 34.7};
auto l = [&total](double w){ total += w; };
sum(temp_c, l);
std::cout << "total: " << total << std::endl;
std::cin.get();
return 0;
}
template <typename T>
void sum(std::array<double, Size> a, T& fp)
{
for (auto pt = a.begin(); pt != a.end(); ++pt)
fp(*pt);
}
And even though the assignment explicitly says not to adapt sum(), if you turn the fp parameter into a const ref, the original temporary variable will compile too - and that would be a much more canonical C++ way of implementing this.