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

У меня есть вопрос о том, как правильно использовать новый C ++ 11 std::function переменная. Я видел несколько примеров из поиска в Интернете, но они, кажется, не охватывают случай использования, который я рассматриваю. Возьмите этот минимальный пример, где функция fdiff является реализацией алгоритма конечной разности вперед, определенного в numerical.hxx (что не проблема, я просто хотел привести контекстную причину, по которой я хотел бы взять произвольную функцию и передать ее).

#include <functional>
#include <iostream>
#include <cmath>
#include "numerical.hxx"
int main()
{
double start = 0.785398163;
double step  = 0.1;
int    order = 2;

std::function<double(double)> f_sin = std::sin;

std::cout << fdiff(start, step, order, f_sin) << std::endl;

return 0;
}

Попытка скомпилировать вышеупомянутую программу дает мне ошибку (в clang ++)

test.cpp:11:32: error: no viable conversion from '<overloaded function type>' to
'std::function<double (double)>'
std::function<double(double)> f_sin = std::sin;
^       ~~~~~~~~
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../include/c++/4.7.1/functional:2048:7: note:
candidate constructor not viable: no overload of 'sin' matching
'nullptr_t' for 1st argument
function(nullptr_t) noexcept
^
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../include/c++/4.7.1/functional:2059:7: note:
candidate constructor not viable: no overload of 'sin' matching 'const
std::function<double (double)> &' for 1st argument
function(const function& __x);
^
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../include/c++/4.7.1/functional:2068:7: note:
candidate constructor not viable: no overload of 'sin' matching
'std::function<double (double)> &&' for 1st argument
function(function&& __x) : _Function_base()
^
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../include/c++/4.7.1/functional:2092:2: note:
candidate template ignored: couldn't infer template argument '_Functor'
function(_Functor __f,
^
1 error generated.

или из g ++

test.cpp: In function ‘int main()’:
test.cpp:11:45: error: conversion from ‘<unresolved overloaded function type>’ to non-scalar type ‘std::function<double(double)>’ requested

Как я понимаю проблема, это потому что std::sin реализован как шаблонный класс в стандартной библиотеке, но я не могу понять, что мне нужно сделать, чтобы получить достаточную специализацию, чтобы получить ссылку на функцию. Я также пробовал разные вещи, такие как использование нового auto ключевое слово, используя &std::sin получить указатель и т. д., но все они дают мне один и тот же тип ошибки.

6

Решение

std::sin перегружена функция: вы должны std::sin Вы имеете в виду перегрузку:

std::function<double(double)> f_sin = (double(*)(double))&std::sin;

В некоторых случаях компилятор может устранить неоднозначность перегруженных функций (например, если f_sin был типа double(*)(double)актерский состав не требуется). Однако это не один из таких случаев.

14

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

С лямбдой вы всегда будете в безопасности:

std::function<double(double)> f_sin = [](double arg) -> double { return std::sin(arg); };

На самом деле вы можете сделать лучше, если вы можете изменить fdiff или он уже принимает параметр шаблона — не просто std::function<double(double)>:

auto f_sin = [](double arg) -> double { return std::sin(arg); };
std::cout << fdiff(start, step, order, f_sin) << std::endl;
[ОБНОВЛЕНИЕ] Этот ответ является новой версией, предыдущий совет использовать специализацию шаблона функции был неверным, поскольку std :: sin — это не шаблон функции, а набор перегруженных функций.

1