21

これがコンパイルされていない理由を検出するのに苦労しています。std::functionいくつかの引数に基づいてを返すラムダ関数があります。

問題を次のスニペットに絞り込みました(ラムダを使用していませんが、エラーを完全に再現しています):

#include <functional>
#include <iostream>


struct foo {
    template<class T>
    void bar(T data) {
        std::cout << data << "\n";
    }
};

void some_fun(const std::function<void(int)> &f) {
    f(12);
}

int main() {
    foo x;
    auto f = std::bind(&foo::bar<int>, x, std::placeholders::_1);
    auto w = std::bind(some_fun, f);
    w();
}

への呼び出しは、w()何が問題なのか理解できない素敵な gcc エラー出力の 1 つを生成します。これは、gcc 4.6.1 によってエコーされるエラーです。

g++ -std=c++0x    test.cpp   -o test
test.cpp: In function ‘int main()’:
test.cpp:20:7: error: no match for call to ‘(std::_Bind<void (*(std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>))(const std::function<void(int)>&)>) ()’
/usr/include/c++/4.6/functional:1130:11: note: candidates are:
/usr/include/c++/4.6/functional:1201:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
/usr/include/c++/4.6/functional:1215:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
/usr/include/c++/4.6/functional:1229:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
/usr/include/c++/4.6/functional:1243:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]

ここでfは、int を引数として取り、それを使用して呼び出す呼び出し可能なオブジェクトが必要x.bar(int)です。一方、wは を呼び出す単なる呼び出し可能オブジェクトでありsome_fun(f)f上記の呼び出し可能オブジェクトであり、some_funのパラメーターによって期待される署名を持っています。

何か不足していますか?と を実際に混合する方法がわからない可能性がstd::bindあり std::functionます。

4

2 に答える 2

21

std::bind式は、boost::bind前任者と同様に、合成操作のタイプをサポートします。あなたの式 forwはほぼ同等です

auto w=std::bind(some_fun,  std::bind(&foo::bar<int>, x, std::placeholders::_1) );

この方法でバインドをネストすると、次のように解釈されます。

  1. 結果のファンクターに渡される最初のパラメーターであるx.bar<int>(y)whereの値を計算します。y
  2. その結果を に渡しsome_funます。

ただしx.bar<int>(y)、関数型ではなく、void を返します。これがコンパイルされない理由です。

K-ballo が指摘しているように、 を使用するとboost::bind、この問題を で修正できますboost::protect。Kerrek SB と ildjarn が指摘しているように、この問題を回避する 1 つの方法は、 for を使用しないことautoですffバインド式の型は必要ありません。f他のタイプの場合std::bind、関数構成規則を適用しようとしません。たとえば、次のようfに typeを指定できstd::function<void(int)>ます。

std::function<void(int)> f = std::bind(&foo::bar<int>, x, std::placeholders::_1);
auto w = std::bind(some_fun, f);

fは文字通りバインド式の型を持たないため、 の型でstd::is_bind_expression<>::valueは false になるfためstd::bind、2 行目の式は、関数合成規則を適用しようとするのではなく、そのまま値を渡すだけです。

于 2012-05-28T00:54:26.140 に答える
-3

some_fun型の引数が必要ですconst std::function<void(int)> &

std::bind は、some_fun 引数として渡そうとする「指定されていない型 T の関数オブジェクト」(提供されたリンクの「戻り値」セクションを参照) を返します。

この引数の型は予期されていないため、これが問題を引き起こしているようです。

見てください:http://en.cppreference.com/w/cpp/utility/functional/bind

于 2012-05-27T21:59:28.110 に答える