You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用std::bind绑定含非默认拷贝构造函数类参数的成员函数报错

关于std::bind绑定带参数成员函数的编译错误问题

问题描述

尝试用std::bind绑定带单个参数的成员函数,初始代码编译正常,但给message类添加自定义拷贝构造函数后出现编译错误。

初始代码

// tester.hpp
#include <functional>

class message
{
  public:
    message()
    {
    }
    //message(message &msg){value = msg.value;} // 取消注释此行会导致错误
    int value = 0;
};

class messageHandler
{
  public:
    messageHandler()
    {
        handleIntFn = std::bind(&messageHandler::handleInt, this, std::placeholders::_1);
        handleMessageFn = std::bind(&messageHandler::handleMsg, this, std::placeholders::_1);
    }

  private:
    bool handleInt(int value)
    {
        return value == 0;
    }
    bool handleMsg(message msg)
    {
        return msg.value == 0;
    }

    std::function<bool(int)> handleIntFn;
    std::function<bool(message)> handleMessageFn;
};

编译错误信息

/home/tester.hpp:19:92: error: no match for 'operator=' (operand types are 'std::function<bool(message)>' and 'std::_Bind_helper<false, bool (messageHandler::*)(message), messageHandler*, const std::_Placeholder<1>&>::type')
   19 |         handleMessageFn = std::bind(&messageHandler::handleMsg, this, std::placeholders::_1);
      |                                                                                            ^
In file included from /usr/include/newlib/c++/10.3.1/functional:59,
                 from /home/tester.hpp:1,
                 from /home/tester.cpp:1:
/usr/include/newlib/c++/10.3.1/bits/std_function.h:396:7: note: candidate: 'std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(const std::function<_Res(_ArgTypes ...)>&) [with _Res = bool; _ArgTypes = {message}]'
  396 |       operator=(const function& __x)
      |       ^~~~~~~~
/usr/include/newlib/c++/10.3.1/bits/std_function.h:396:33: note:   no known conversion for argument 1 from 'std::_Bind_helper<false, bool (messageHandler::*)(message), messageHandler*, const std::_Placeholder<1>&>::type' to 'const std::function<bool(message)>&'
  396 |       operator=(const function& __x)
      |                 ~~~~~~~~~~~~~~~~^~~
/usr/include/newlib/c++/10.3.1/bits/std_function.h:414:7: note: candidate: 'std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::function<_Res(_ArgTypes ...)>&&) [with _Res = bool; _ArgTypes = {message}]'
  414 |       operator=(function&& __x) noexcept
      |       ^~~~~~~~
/usr/include/newlib/c++/10.3.1/bits/std_function.h:414:28: note:   no known conversion for argument 1 from 'std::_Bind_helper<false, bool (messageHandler::*)(message), messageHandler*, const std::_Placeholder<1>&>::type' to 'std::function<bool(message)>&&'
  414 |       operator=(function&& __x) noexcept
      |                 ~~~~~~~~~~~^~~
/usr/include/newlib/c++/10.3.1/bits/std_function.h:428:7: note: candidate: 'std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::nullptr_t) [with _Res = bool; _ArgTypes = {message}; std::nullptr_t = std::nullptr_t]'
  428 |       operator=(nullptr_t) noexcept
      |       ^~~~~~~~
/usr/include/newlib/c++/10.3.1/bits/std_function.h:428:17: note:   no known conversion for argument 1 from 'std::_Bind_helper<false, bool (messageHandler::*)(message), messageHandler*, const std::_Placeholder<1>&>::type' to 'std::nullptr_t'
  428 |       operator=(nullptr_t) noexcept
      |                 ^~~~~~~~~
/usr/include/newlib/c++/10.3.1/bits/std_function.h:457:2: note: candidate: 'template<class _Functor> std::function<_Res(_ArgTypes ...)>::_Requires<std::function<_Res(_ArgTypes ...)>::_Callable<typename std::decay<_Functor>::type>, std::function<_Res(_ArgTypes ...)>&> std::function<_Res(_ArgTypes ...)>::operator=(_Functor&&) [with _Functor = _Functor; _Res = bool; _ArgTypes = {message}]'
  457 |  operator=(_Functor&& __f)
      |  ^~~~~~~~
/usr/include/newlib/c++/10.3.1/bits/std_function.h:457:2: note:   template argument deduction/substitution failed:
/usr/include/newlib/c++/10.3.1/bits/std_function.h: In substitution of 'template<class _Res, class ... _ArgTypes> template<class _Cond, class _Tp> using _Requires = typename std::enable_if<_Cond::value, _Tp>::type [with _Cond = std::function<bool(message)>::_Callable<std::_Bind<bool (messageHandler::*(messageHandler*, std::_Placeholder<1>))(message)>, std::__invoke_result<std::_Bind<bool (messageHandler::*(messageHandler*, std::_Placeholder<1>))(message)&, message> >; _Tp = std::function<bool(message)>&; _Res = bool; _ArgTypes = {message}]':
/usr/include/newlib/c++/10.3.1/bits/std_function.h:457:2:   required by substitution of 'template<class _Functor> std::function<bool(message)>::_Requires<std::function<bool(message)>::_Callable<typename std::decay<_Tp>::type, std::__invoke_result<typename std::decay<_Tp>::type&, message> >, std::function<bool(message)>&> std::function<bool(message)>::operator=<(_Functor&&) [with _Functor = std::_Bind<bool (messageHandler::*(messageHandler*, std::_Placeholder<1>))(message)>]'
/home/tester.hpp:19:92:   required from here
/usr/include/newlib/c++/10.3.1/bits/std_function.h:319:8: error: no type named 'type' in 'struct std::enable_if<false, std::function<bool(message)>&>'
  319 |  using _Requires = typename enable_if<_Cond::value, _Tp>::type;
      |        ^~~~~~~~~
/usr/include/newlib/c++/10.3.1/bits/std_function.h:466:2: note: candidate: 'template<class _Functor> std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::reference_wrapper<_Functor>) [with _Functor = _Functor; _Res = bool; _ArgTypes = {message}]'
  466 |  operator=(reference_wrapper<_Functor> __f) noexcept
      |  ^~~~~~~~
/usr/include/newlib/c++/10.3.1/bits/std_function.h:466:2: note:   template argument deduction/substitution failed:
In file included from /home/tester.cpp:1:
/home/tester.hpp:19:92: note:   'std::_Bind<bool (messageHandler::*(messageHandler*, std::_Placeholder<1>))(message)>' is not derived from 'std::reference_wrapper<_Tp>'
   19 |         handleMessageFn = std::bind(&messageHandler::handleMsg, this, std::placeholders::_1);
      |

疑问:std::bind是否依赖默认拷贝构造函数?为何无法使用自定义拷贝构造函数?预期它应该支持带有拷贝构造函数的类。

解答

问题根源

不是std::bind依赖默认拷贝构造函数,而是自定义拷贝构造函数的参数为非常量引用,导致类型兼容性冲突:

  • 当定义message(message &msg)时,编译器会自动禁用默认的const message&版本拷贝构造函数。
  • handleMsg的参数是值传递message msg,调用时需要从临时对象(右值)构造参数,但右值无法绑定到非常量引用的拷贝构造函数参数上。
  • std::function在验证std::bind生成的对象是否可匹配bool(message)签名时,发现无法完成参数构造,因此触发编译错误。

解决方法

将自定义拷贝构造函数的参数改为常量引用即可:

message(const message &msg){value = msg.value;}

补充说明

  • 自定义拷贝构造函数使用const引用是C++的标准实践,既能兼容右值临时对象,也符合常量正确性原则。
  • 若确实需要非常量引用的拷贝构造函数(极少场景),可将handleMsg的参数改为message&,但这会限制函数只能接受左值,灵活性较差。

内容的提问来源于stack exchange,提问作者Kiwewi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:39:50