【问题标题】:Using bind1st for a method that takes argument by reference将 bind1st 用于通过引用获取参数的方法
【发布时间】:2026-02-22 16:05:02
【问题描述】:

我有一个这样的结构:

struct A {
    void i(int i) {}
    void s(string const &s) {}
};

现在当我尝试这个时:

bind1st(mem_fun(&A::i), &a)(0);
bind1st(mem_fun(&A::s), &a)("");

第一行编译OK,第二行报错:

c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional(299): error C2535: 'void std::binder1st<_Fn2>::operator ()(const std::basic_string<_Elem,_Traits,_Ax> &) const' : member function already defined or declared
          with
          [
              _Fn2=std::mem_fun1_t<void,A,const std::string &>,
              _Elem=char,
              _Traits=std::char_traits<char>,
              _Ax=std::allocator<char>
          ]
          c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional(293) : see declaration of 'std::binder1st<_Fn2>::operator ()'
          with
          [
              _Fn2=std::mem_fun1_t<void,A,const std::string &>
          ]
          c:\work\sources\exception\test\exception\main.cpp(33) : see reference to class template instantiation 'std::binder1st<_Fn2>' being compiled
          with
          [
              _Fn2=std::mem_fun1_t<void,A,const std::string &>
          ]

可能是什么问题?我该如何解决?

编辑:

似乎任何引用参数都是一个问题。因此,如果我将 i 方法更改为 void i(int &amp;i) {} 我会收到类似的错误。

【问题讨论】:

  • 鉴于我们是在 2011 年并且拥有 C++11,您可能想看看 C++11s std::bindboost::bind,它们使这些数量级的事情更容易处理。
  • @PlasmaHH:不幸的是,我不能在这个项目中使用 C++11。

标签: c++ visual-c++


【解决方案1】:

std::bind1st 和 std::bind2nd 不接受接受引用参数的函子,因为它们本身形成对这些参数的引用。你可以

  1. 对函数输入使用指针而不是引用
  2. 使用 boost::bind
  3. 接受复制字符串的性能成本

【讨论】:

    【解决方案2】:

    问题是库规范中的缺陷。

    看看这个针对 gcc 的错误报告以及由此产生的讨论:Bug 37811 - bind1st fails on mem_fun with reference argument

    C++03 缺乏构建完美绑定库的工具。此问题已在 C++11 中通过完美转发和 std::bind 修复。

    【讨论】:

      【解决方案3】:

      看看这个post对模板参数的要求进行了解释。 正如您已经假设对 std::string 的引用是问题所在。这不是一个有效的模板参数。

      【讨论】:

      • 虽然这是真的,但函数的参数类型通过 first_argument_type typedef 从 mem_fun 传输到 bind1st,并且引用是有效的 typedef。所以 std::bind1st 可以理论上接受引用,但实现方式不同(并且此实现是由标准 IIRC 强制执行的)。
      【解决方案4】:

      通过指针改变引用

      #include <functional>
      #include <string>
      
      struct A {
          void i(int i) {}
          void s(const std::string *s) {}
      };
      
      
      int main(void)
      {
          A a;
          std::bind1st(std::mem_fun(&A::i), &a)(0);
          const std::string s("");
          std::bind1st(std::mem_fun(&A::s), &a)(&s);
      }
      

      【讨论】: