7

std::function新しいC++11変数を適切に使用する方法について質問があります。インターネットを検索していくつかの例を見てきましたが、それらは私が検討している使用例をカバーしていないようです。この最小の例を見てください。ここで、関数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は、標準ライブラリにテンプレートクラスとして実装されているためですが、関数参照を取得するために十分な特殊化を行うために何をする必要があるのか​​理解できないようです。autoまた、新しいキーワードを使用&std::sinしたり、ポインタを取得したりするなど、さまざまなことを試しましたが、すべて同じタイプのエラーが発生します。

4

2 に答える 2

16

std::sinオーバーロードされた関数です:std::sin意味するオーバーロードを明確にする必要があります:

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

コンパイラーがオーバーロードされた関数を明確にできる場合があります(たとえば、f_sinタイプがの場合double(*)(double)、キャストは必要ありません)。ただし、これはそのようなケースの1つではありません。

于 2012-09-19T18:12:46.497 に答える
2

ラムダを使用すると、常に安全な側になります:

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 に答える