I am coming somewhat belatedly to Functional Programming, and getting my head around ranges/views. I'm using MSVC19 and compiling for C++ 20.
I'm using std::views::transform and the compiler doesn't seem to be inferring type as I might naively hope.
Here's a small example, which simply takes a vector of strings and computes their length:
#include <vector>
#include <iostream>
#include <ranges>
template<typename E>
auto length(const E& s)
{
std::cout << "Templated length()\n";
return static_cast<int>(s.length());
}
template<typename E>
auto getLengths(const std::vector<E>& v)
{
return v | std::views::transform(length<E>);
}
int main()
{
std::vector<std::string> vec = { "Larry","Curly","Moe" };
for (int i : getLengths(vec))
{
std::cout << i << "\n";
}
return 0;
}
with the output:
Templated length()
5
Templated length()
5
Templated length()
3
My question is why does changing the code in this line (dropping the <E>):
return v | std::views::transform(length);
give me an armful of errors, starting with: Error C2672 'operator __surrogate_func': no matching overloaded function found ?
Why doesn't the compiler infer that the type is std::string? If I replace the templates with a non-templated function:
auto length(const std::string& s) -> int
{
std::cout << "Specialized length()\n";
return static_cast<int>(s.length());
}
The code compiles and runs, so clearly without the template, the compiler finds a match for the particular type I am using.