7

我有一个关于如何正确使用新的 C++11std::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 ‘&lt;unresolved overloaded function type>’ to non-scalar type ‘std::function<double(double)>’ requested

据我了解这个问题,这是因为std::sin在标准库中实现为模板类,但我似乎无法弄清楚我需要做些什么来提供足够的专业化来获得函数引用。我还尝试了各种方法,例如使用 newauto关键字、&std::sin用于获取指针等,但它们都给了我相同类型的错误。

4

2 回答 2

16

std::sin is an overloaded function: you must disambiguate which std::sin overload you mean:

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

There are some cases where the compiler can disambiguate overloaded functions (e.g., if f_sin was of type double(*)(double), the cast would not be required). However, this is not one of those cases.

于 2012-09-19T18:12:46.497 回答
2

使用 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 不是函数模板而是一组重载函数。

于 2012-09-19T18:09:04.330 回答