4

次のコードがコンパイルされない理由がわかりません。

#include <memory>
#include <functional>

class Foo 
{
public:
  void Bar(int i) {}
};

void X(std::function<void(std::shared_ptr<Foo>)> f)
{

}

int main()
{
  std::shared_ptr<Foo> f(new Foo);
  auto f1(std::bind(&Foo::Bar, std::placeholders::_1, 1));
  X(f1);
  return 0;
}

g++ (4.6.3) 出力...

n file included from /usr/include/c++/4.6/memory:80:0,
                 from test.cpp:1:
/usr/include/c++/4.6/functional: In static member function ‘static void std::_Function_handler<void(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Functor = std::_Bind<std::_Mem_fn<void (Foo::*)(int)>(std::_Placeholder<1>, int)>, _ArgTypes = {std::shared_ptr<Foo>}]’:
/usr/include/c++/4.6/functional:2148:6:   instantiated from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = std::_Bind<std::_Mem_fn<void (Foo::*)(int)>(std::_Placeholder<1>, int)>, _Res = void, _ArgTypes = {std::shared_ptr<Foo>}, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<void(std::shared_ptr<Foo>)>::_Useless]’
test.cpp:19:7:   instantiated from here
/usr/include/c++/4.6/functional:1778:2: error: no match for call to ‘(std::_Bind<std::_Mem_fn<void (Foo::*)(int)>(std::_Placeholder<1>, int)>) (std::shared_ptr<Foo>)’
/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 = std::_Mem_fn<void (Foo::*)(int)>, _Bound_args = {std::_Placeholder<1>, int}]
/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 = std::_Mem_fn<void (Foo::*)(int)>, _Bound_args = {std::_Placeholder<1>, int}]
/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 = std::_Mem_fn<void (Foo::*)(int)>, _Bound_args = {std::_Placeholder<1>, int}]
/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 = std::_Mem_fn<void (Foo::*)(int)>, _Bound_args = {std::_Placeholder<1>, int}]
4

1 に答える 1

5

これは GCC のバグで、4.7 で修正しましたが、どのバグか正確には覚えていません。私はそれを理解しようとします...

編集:ああ、それはPR 55463なので、4.7では修正されていません.GCCトランクでのみ修正されています(4.8になります)

バグは、によって返された呼び出しラッパーが右辺値をmem_fn受け入れず、std::function<void(std::shared_ptr<Foo>)型が右辺値shared_ptr<Foo>を呼び出しラッパー return by に渡すことでしたbind

回避策として、関数のシグネチャを次のように変更できます。

void X(std::function<void(const std::shared_ptr<Foo>&)> f)

修正を 4.7 ブランチにバックポートすることはできないと思います。なぜなら、そのバグの結果としてmem_fn、安定版リリース ブランチにはあまり適していない非常に大きな変更をいくつか行ったからです (標準のブランチにも新しい欠陥が見つかりました)。 )

于 2012-12-19T19:16:50.477 に答える