Указатель на функцию и std :: function: первый компилируется, а не второй?

Я не знаком с указателем на функции, и в настоящее время я делаю некоторые тесты. Но в следующей программе я не понимаю, почему первая версия работает и почему вторая версия не компилируется. Какой будет правильный синтаксис?

#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;
}

Ошибка заключается в следующем:

error: cannot resolve overloaded function 'iota' based on conversion to type 'std::function<void(double*, double*, double)>'

1

Решение

Указатель на функцию предоставляет то, что я называю контекст преобразования. В нем четко указано, какая из перегрузок имеется в виду, в то время как std::function не. Конструктор std::function принимает любую вызываемую сущность и, таким образом, не предоставляет контекста для однозначного определения, какая перегрузка подразумевается. Смотрите также этот вопрос.

Чтобы устранить неоднозначность вручную, либо приведите указатель на функцию

apply2(v, static_cast<void(*)(double*,double*,double)>(std::iota));

или использовать указатель на именованную функцию

void (*iota)(double*, double*, double) = std::iota;
apply2(v, iota);

или используйте лямбду

apply2(v, [](double* f, double* l, double d){ std::iota(f, l, d); });
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]