Reputation: 60381
I'm not familiar with pointer to functions and I'm currently making some tests. But in the following program, I don't understand why the first version works and why the second version does not compile. What would be the correct syntax ?
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
template<typename Type>
void display(const std::vector<Type>& v)
{
if (!v.empty()) {
for (unsigned int i = 0; i < v.size()-1; ++i)
std::cout<<v[i]<<" ";
std::cout<<v[v.size()-1];
}
}
// Compiles
template<typename Type>
void apply1(std::vector<Type>& v, void(f)(Type*, Type*, Type))
{
f(&*v.begin(), &*v.end(), 0);
}
// Does not compile
template<typename Type>
void apply2(std::vector<Type>& v, std::function<void(Type*, Type*, Type)> f)
{
f(&*v.begin(), &*v.end(), 0);
}
int main()
{
std::vector<double> v = {1., 2., 3., 4., 5., 6.};
display(v); std::cout<<std::endl;
apply1(v, std::iota);
display(v); std::cout<<std::endl;
apply2(v, std::iota);
display(v); std::cout<<std::endl;
return 0;
}
The error is the following :
error: cannot resolve overloaded function 'iota' based on conversion to type 'std::function<void(double*, double*, double)>'
Upvotes: 1
Views: 191
Reputation: 131799
A function pointer provides what I call a conversion context. It explicitly states which of the overloads is meant, whilst std::function
does not. The constructor of std::function
takes in any callable entity and as such provides no context to disambiguate which overload is meant. See also this question.
To manually disambiguate, either cast the function pointer
apply2(v, static_cast<void(*)(double*,double*,double)>(std::iota));
or use a named function pointer
void (*iota)(double*, double*, double) = std::iota;
apply2(v, iota);
or use a lambda
apply2(v, [](double* f, double* l, double d){ std::iota(f, l, d); });
Upvotes: 3