我有一个关于如何正确使用新的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
获取指针等,但它们都给了我相同类型的错误。
答案 0 :(得分:14)
std::sin
是一个重载函数:您必须消除歧义std::sin
重载的意义:
std::function<double(double)> f_sin = (double(*)(double))&std::sin;
在某些情况下,编译器可以消除重载函数的歧义(例如,如果f_sin
类型为double(*)(double)
,则不需要强制转换)。但是,这不是其中之一。
答案 1 :(得分:1)
使用lambda,您将永远保持安全:
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不是函数模板而是重载函数集。