Setting a std::function variable to refer to the std::sin function

こ雲淡風輕ζ 提交于 2020-01-22 19:38:29

问题


I've got a question about how to properly use the new C++11 std::function variable. I've seen several examples from searching the Internet, but they don't seem to cover the usage case I'm considering. Take this minimum example, where the function fdiff is an implementation of the finite forward differencing algorithm defined in numerical.hxx (which isn't the problem, I just wanted to give a contextual reason why I'd want to take an arbitrary function and pass it around).

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

Attempting to compile the above program gives me the error (in 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.

or from 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

As I understand the problem, it's because std::sin is implemented as a template class in the standard library, but I can't seem to figure out what I need to do to give enough of a specialization to get a function reference. I've also tried various things like using the new auto keyword, using &std::sin to get a pointer, etc., but they all give me the same type of error.


回答1:


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.




回答2:


With lambda you will be always on safe side:

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

Actually you can do better, if you can change fdiff or it is already accepting template parameter - not just std::function<double(double)>:

auto f_sin = [](double arg) -> double { return std::sin(arg); };
std::cout << fdiff(start, step, order, f_sin) << std::endl;

[UPDATE] This answer is new version, previous advice to use function template specialization was incorrect, since std::sin is not function template but set of overloaded functions.



来源:https://stackoverflow.com/questions/12500411/setting-a-stdfunction-variable-to-refer-to-the-stdsin-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!