【问题标题】:referencing a member function with bind1st and mem_fun使用 bind1st 和 mem_fun 引用成员函数
【发布时间】:2013-09-04 21:09:46
【问题描述】:

我有一个 C++ 类,我正在尝试使用 std::bind1st 将成员函数绑定到“this”参数。例如:

class MyClass
{
public:
   void Foo()
   {
       using namespace std;

       // this works fine
       this->Bar();

       // this also works fine
       mem_fun( &MyClass::Bar )( this );

       // this does not
       bind1st( mem_fun( &MyClass::Bar ), this )();

       // this is not a possibility for this program
       boost::bind( &MyClass::Bar, this )();
   };

   void Bar()
   {
   };
};

当我添加最后的 'bind1st' 行时,我收到以下编译器错误:

1>stl/_function.h(189) : error C2039: 'second_argument_type' : is not a member of 'stlp_std::mem_fun_t<_Ret,_Tp>'
1>        with
1>        [
1>            _Ret=void,
1>            _Tp=MyClass
1>        ]
1>        .\MyClass.cpp(50) : see reference to class template instantiation 'stlp_std::binder1st<_Operation>' being compiled
1>        with
1>        [
1>            _Operation=stlp_std::mem_fun_t<void,MyClass>
1>        ]
1>stl/_function.h(189) : error C2146: syntax error : missing ',' before identifier 'second_argument_type'
1>stl/_function.h(189) : error C2065: 'second_argument_type' : undeclared identifier
1>stl/_function.h(190) : error C2955: 'stlp_std::unary_function' : use of class template requires template argument list
1>        stl/_function_base.h(40) : see declaration of 'stlp_std::unary_function'
1>stl/_function.h(191) : error C2039: 'second_argument_type' : is not a member of 'stlp_std::mem_fun_t<_Ret,_Tp>'
1>        with
1>        [
1>            _Ret=void,
1>            _Tp=MyClass
1>        ]
1>stl/_function.h(191) : error C2146: syntax error : missing ',' before identifier 'second_argument_type'
1>stl/_function.h(191) : error C2065: 'second_argument_type' : undeclared identifier
1>stl/_function.h(194) : error C2955: 'stlp_std::unary_function' : use of class template requires template argument list
1>        stl/_function_base.h(40) : see declaration of 'stlp_std::unary_function'
1>stl/_function.h(195) : error C2955: 'stlp_std::unary_function' : use of class template requires template argument list
1>        stl/_function_base.h(40) : see declaration of 'stlp_std::unary_function'
1>stl/_function.h(197) : error C2146: syntax error : missing ';' before identifier '_ArgParamType'
1>stl/_function.h(197) : error C3254: 'stlp_std::binder1st<_Operation>' : class contains explicit override 'param_type' but does not derive from an interface that contains the function declaration
1>        with
1>        [
1>            _Operation=stlp_std::mem_fun_t<void,MyClass>
1>        ]
1>stl/_function.h(197) : error C2838: 'param_type' : illegal qualified name in member declaration
1>stl/_function.h(197) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>stl/_function.h(197) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>stl/_function.h(198) : error C2146: syntax error : missing ';' before identifier '_ConstArgParamType'
1>stl/_function.h(198) : error C3254: 'stlp_std::binder1st<_Operation>' : class contains explicit override 'const_param_type' but does not derive from an interface that contains the function declaration
1>        with
1>        [
1>            _Operation=stlp_std::mem_fun_t<void,MyClass>
1>        ]
1>stl/_function.h(198) : error C2838: 'const_param_type' : illegal qualified name in member declaration
1>stl/_function.h(198) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>stl/_function.h(198) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>stl/_function.h(199) : error C2039: 'first_argument_type' : is not a member of 'stlp_std::mem_fun_t<_Ret,_Tp>'
1>        with
1>        [
1>            _Ret=void,
1>            _Tp=MyClass
1>        ]
1>stl/_function.h(199) : error C2146: syntax error : missing ',' before identifier 'first_argument_type'
1>stl/_function.h(199) : error C2065: 'first_argument_type' : undeclared identifier
1>stl/_function.h(199) : error C2955: 'stlp_std::__call_traits' : use of class template requires template argument list
1>        stl/type_traits.h(452) : see declaration of 'stlp_std::__call_traits'
1>stl/_function.h(203) : error C2039: 'first_argument_type' : is not a member of 'stlp_std::mem_fun_t<_Ret,_Tp>'
1>        with
1>        [
1>            _Ret=void,
1>            _Tp=MyClass
1>        ]
1>stl/_function.h(203) : error C2146: syntax error : missing ';' before identifier '_M_value'
1>stl/_function.h(203) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>stl/_function.h(203) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>stl/_function.h(208) : error C2061: syntax error : identifier '_ConstArgParamType'
1>stl/_function.h(211) : error C2061: syntax error : identifier '_ArgParamType'
1>stl/_function.h(212) : error C2535: '_Result stlp_std::binder1st<_Operation>::operator ()(void) const' : member function already defined or declared
1>        with
1>        [
1>            _Operation=stlp_std::mem_fun_t<void,MyClass>
1>        ]
1>        stl/_function.h(208) : see declaration of 'stlp_std::binder1st<_Operation>::operator ()'
1>        with
1>        [
1>            _Operation=stlp_std::mem_fun_t<void,MyClass>
1>        ]

我正在使用 STLPort v5.2.1 实现标准库。

通常,我会切换到 boost::bind 并使用它。不幸的是,这个应用程序不可能做到这一点。

我可以做些什么来获得我正在寻找的功能?

谢谢, 保罗H


编辑: 更清楚地说,我正在寻找一种方法来使一元函数适应您调用的不带参数的函数。我想将this“绑定”到MyClass::Bar

class SomeOtherClass
{
public:
    template< typename Fcn >
    void ExecuteFcn( Fcn fcn )
    {
        fcn();
    };
};

some_other_class.ExecuteFcn( bind1st( mem_fun( &MyClass::Bar ), this );

【问题讨论】:

  • 是的,我不相信不使用bind 就可以做到这一点。您可以创建一个简单的包装器来执行此操作,就像我在回答中提到的那样,但除此之外,我认为标准库没有任何其他内置方法可以做到这一点。

标签: c++ stl mem-fun


【解决方案1】:

你想用 bind1st 完成什么?

bind1st 函数采用二元函数并通过隐含第一个参数将其调整为一元函数(这可能不是最好的描述,抱歉)。 mem_fun 的返回值是一元函数。

mem_fun 函数返回成员函数的适配器。适配函数不接受任何参数,尽管返回的适配器接受一个参数,一个指向要使用的 MyClass 对象的指针。

所以,基本上,您的 mem_fun 调用返回一个带有一个参数的适配器,但 bind1st 期望一个带有两个参数的适配器。有一个 mem_fun1 返回一个带有两个参数的适配器,第一个是对象指针,第二个是函数的参数,但这不是你想要的。

事实上,我不太明白你想做什么;为什么普通的mem_fun 版本不适合?如果您需要将对象指针“附加”到适配器,我认为您不能使用当前的标准库来做到这一点,除非您使用绑定。

当然,您可以创建一个包含对象指针的包装类,然后只需定义 operator() 以使用该对象调用适配器。

// Quick and dirty example of this.
// You could extend this with a second template parameter for return type, if
// needed. Just be sure to specialize for void if you do that.
template<typename Object>
struct bound_mem_fun_t { 
    bound_mem_fun_t(mem_fun_t<void, Object> f, Object* o) : fun(f), obj(o) { } 
    void operator()() { fun(obj); } 
    mem_fun_t<void, Object> fun; 
    Object* obj; 
};

MyClass a;
bound_mem_fun_t<MyClass> func(mem_fun(&MyClass::Bar), &a);
func();

【讨论】:

    【解决方案2】:

    bind1st 需要一个二元函数,并返回一个一元函子。在这里,您传递一个一元函数。

    “绑定”的目的是通过将其参数之一设置为给定值来使用二元函数/仿函数(如具有一个参数的非静态方法),就像一元函数一样。

    这会起作用(注意Bar 的新原型):

    class MyClass
    {
    public:
       void Foo()
       {
           using namespace std;
    
           // this works fine
           bind1st( mem_fun( &MyClass::Bar ), this )(42);
       };
    
       void Bar(int i)
       {
       };
    };
    

    【讨论】:

      【解决方案3】:

      我想为此添加另一种可能的解决方案,那就是使用 C++11 中的 lambda 函数。

      这是一个简单的例子:

      class MyClass
      {
          std::string mName;
      
      public:
         MyClass(const char* name) : mName(name) {};
      
         void Foo()
         {
             std::cout << "My name is " << mName << std::endl;
         };
      };
      
      void CallMyFn(std::function<void()> fn)
      {
          fn();
      }
      
      int main()
      {
          MyClass myInstance("Ishmael");
      
          CallMyFn( [&]() { myInstance.Foo(); } );
      
          return 0;
      }
      

      输出:“我叫以实玛利。”

      【讨论】:

        【解决方案4】:

        我认为它不起作用,因为bind1st() 需要一个二进制函数对象并返回一个一元函数对象。由于Bar() 没有参数,mem_fun() 给你一个一元函数对象。 bind1st() 不知道该怎么办。

        您实际上打算如何使用mem_fun() 生成的函数对象?

        【讨论】:

        • 我认为问题是,如何获取一元函数对象,并通过将其绑定到参数来生成空函数对象。即 bind1st 的一个版本,但用于较少数量的函数对象。在这种情况下,调用时的空函数对象将调用 this-&gt;Bar () 以获得绑定时使用的 this 的值。
        猜你喜欢
        • 2011-02-24
        • 2023-03-30
        • 1970-01-01
        • 2011-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多