使用unique_ptr参数绑定函数到std :: function< void()> [英] Binding functions with unique_ptr arguments to std::function<void()>

查看:777
本文介绍了使用unique_ptr参数绑定函数到std :: function< void()>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让以下代码工作:

#include <cstdio>
#include <functional>
#include <string>
#include <memory>

using namespace std;

class Foo {
public:
    Foo(): m_str("foo") { }

    void f1(string s1, string s2, unique_ptr<Foo> p)
        {
            printf("1: %s %s %s\n", s1.c_str(), s2.c_str(), p->str());
        }

    void f2(string s1, string s2, Foo* p)
        {
            printf("2: %s %s %s\n", s1.c_str(), s2.c_str(), p->str());
        }

    const char* str() const { return m_str.c_str(); }

private:
    string m_str;
};

int main()
{
    string arg1 = "arg1";
    string arg2 = "arg2";
    Foo s;
    unique_ptr<Foo> ptr(new Foo);


    //function<void()> f(bind(&Foo::f1, &s, arg1, arg2, std::move(ptr)));
    function<void()> f(bind(&Foo::f2, &s, arg1, arg2, ptr.release()));

    f();
}

调用f()绑定到Foo :: f2指针)工作正常,但绑定到Foo :: f1导致编译错误:

Calling f() bound to Foo::f2(last parameter is a raw pointer) works fine, but binding it to Foo::f1 causes compilation error:

test.cpp: In function ‘int main()’:
test.cpp:36:70: error: no matching function for call to ‘std::function<void()>::function(std::_Bind_helper<false, void (Foo::*)(std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>), Foo*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::unique_ptr<Foo, std::default_delete<Foo> > >::type)’
     function<void()> f(bind(&Foo::f1, &s, arg1, arg2, std::move(ptr)));
                                                                      ^
test.cpp:36:70: note: candidates are:
In file included from test.cpp:2:0:
/usr/include/c++/4.8.2/functional:2251:2: note: template<class _Functor, class> std::function<_Res(_ArgTypes ...)>::function(_Functor)
  function(_Functor);
  ^
/usr/include/c++/4.8.2/functional:2251:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.8.2/functional:2226:7: note: std::function<_Res(_ArgTypes ...)>::function(std::function<_Res(_ArgTypes ...)>&&) [with _Res = void; _ArgTypes = {}]
       function(function&& __x) : _Function_base()
       ^
/usr/include/c++/4.8.2/functional:2226:7: note:   no known conversion for argument 1 from ‘std::_Bind_helper<false, void (Foo::*)(std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>), Foo*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::unique_ptr<Foo, std::default_delete<Foo> > >::type {aka std::_Bind<std::_Mem_fn<void (Foo::*)(std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>)>(Foo*, std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>)>}’ to ‘std::function<void()>&&’
/usr/include/c++/4.8.2/functional:2429:5: note: std::function<_Res(_ArgTypes ...)>::function(const std::function<_Res(_ArgTypes ...)>&) [with _Res = void; _ArgTypes = {}]
     function<_Res(_ArgTypes...)>::
     ^
/usr/include/c++/4.8.2/functional:2429:5: note:   no known conversion for argument 1 from ‘std::_Bind_helper<false, void (Foo::*)(std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>), Foo*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::unique_ptr<Foo, std::default_delete<Foo> > >::type {aka std::_Bind<std::_Mem_fn<void (Foo::*)(std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>)>(Foo*, std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>)>}’ to ‘const std::function<void()>&’
/usr/include/c++/4.8.2/functional:2206:7: note: std::function<_Res(_ArgTypes ...)>::function(std::nullptr_t) [with _Res = void; _ArgTypes = {}; std::nullptr_t = std::nullptr_t]
       function(nullptr_t) noexcept
       ^
/usr/include/c++/4.8.2/functional:2206:7: note:   no known conversion for argument 1 from ‘std::_Bind_helper<false, void (Foo::*)(std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>), Foo*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::unique_ptr<Foo, std::default_delete<Foo> > >::type {aka std::_Bind<std::_Mem_fn<void (Foo::*)(std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>)>(Foo*, std::basic_string<char>, std::basic_string<char>, std::unique_ptr<Foo>)>}’ to ‘std::nullptr_t’
/usr/include/c++/4.8.2/functional:2199:7: note: std::function<_Res(_ArgTypes ...)>::function() [with _Res = void; _ArgTypes = {}]
       function() noexcept
       ^
/usr/include/c++/4.8.2/functional:2199:7: note:   candidate expects 0 arguments, 1 provided

我做错了什么?

m使用gcc 4.8.2和-std = c ++ 0x(-std = c ++ 11也失败)标志。

I'm using gcc 4.8.2 and -std=c++0x(-std=c++11 fails too) flags.

感谢

推荐答案

在其他答案中描述的问题(在撰写本文时)不是编译器在问题中抱怨的问题。问题是 std :: function 必须是CopyConstructible,它需要它的参数(将由函数存储)也是CopyConstructible。

The issues with bind described in the other answers (as of this writing) are not what the compiler is complaining about in the question. The problem is that std::function must be CopyConstructible, which requires its argument (which will be stored by the function) also be CopyConstructible.

从标准[20.9.11.2类模板功能]

From the standard [20.9.11.2 Class template function]

template<class F> function(F f); 
template <class F, class A> function(allocator_arg_t, const A& a, F f);




需要:F必须是CopyConstructible。 f对于参数类型为ArgTypes和返回类型为R,应为Callable(20.9.11.2)。 A的复制构造函数和析构函数不会抛出异常...

Requires: F shall be CopyConstructible. f shall be Callable (20.9.11.2) for argument types ArgTypes and return type R . The copy constructor and destructor of A shall not throw exceptions...

考虑这个例子,

#include <functional>
#include <memory>

using namespace std;

struct NonCopyableFunctor {
  NonCopyableFunctor(){}
  NonCopyableFunctor(const NonCopyableFunctor &) = delete;
  NonCopyableFunctor(NonCopyableFunctor &&){}
  void operator()(){}
};

int main() 
{
  NonCopyableFunctor fun;
  function<void()> vfun(move(fun)); // even though I move here,
  // it still complains about a copy going on elsewhere.
}

这是clang的输出:

Here's the output from clang:

[orm@localhost ~]$ clang++ -std=c++11 bound_unique.cc 
In file included from bound_unique.cc:1:
/usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/functional:1911:10: error: call to deleted constructor of 'NonCopyableFunctor'
            new _Functor(*__source._M_access<_Functor*>());
                ^        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/functional:1946:8: note: in instantiation of member function
      'std::_Function_base::_Base_manager<NonCopyableFunctor>::_M_clone' requested here
              _M_clone(__dest, __source, _Local_storage());
              ^
/usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/functional:2453:33: note: in instantiation of member function
      'std::_Function_base::_Base_manager<NonCopyableFunctor>::_M_manager' requested here
            _M_manager = &_My_handler::_M_manager;
                                       ^
bound_unique.cc:16:20: note: in instantiation of function template specialization 'std::function<void ()>::function<NonCopyableFunctor, void>' requested here
  function<void()> vfun(move(fun));
                   ^
bound_unique.cc:8:3: note: function has been explicitly marked deleted here
  NonCopyableFunctor(const NonCopyableFunctor &) = delete;
  ^
1 error generated.

请注意,如果绑定一个unique_ptr,生成的绑定对象将是不可复制的。 Bind仍然会编译。

Note that if you bind a unique_ptr, the resulting bind object will be non-copyable. Bind will still compile anyway.

这篇关于使用unique_ptr参数绑定函数到std :: function&lt; void()&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆