代码之家  ›  专栏  ›  技术社区  ›  Nicola Bonelli

tr1::mem_fn和tr1::bind:关于常量正确性和重载

  •  4
  • Nicola Bonelli  · 技术社区  · 17 年前

    以下代码段有什么问题?

    #include <tr1/functional>
    #include <functional>
    #include <iostream>
    
    using namespace std::tr1::placeholders;
    
    struct abc
    {
        typedef void result_type;
    
        void hello(int)
        { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    
        void hello(int) const
        { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    
        abc()
        {}
    };
    
    int
    main(int argc, char *argv[])
    {
        const abc x;
        int a = 1;
    
        std::tr1::bind(&abc::hello, x , _1)(a);
        return 0;
    }
    

    tr1::mem_fn<> 和 tr1::bind<> 然后得出以下错误:

    no matching function for call to ‘bind(<unresolved overloaded function type>,...
    

    相反,下面的代码段进行了编译,但似乎破坏了 :

    struct abc
    {
        typedef void result_type;
    
        void operator()(int)
        { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    
        void operator()(int) const
        { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    
        abc()
        {}
    };
    
    ...
    
        const abc x;
        int a = 1;
        std::tr1::bind( x , _1)(a);
    

    有线索吗?

    3 回复  |  直到 17 年前
        1
  •  4
  •   John Zwinck    17 年前

    查找是在 this

    typedef void (abc::*fptr)(int) const; // or remove const
    std::tr1::bind((fptr)&abc::hello, x , _1)(a);
    

    您可能还注意到,在此处删除 const 参数,始终是指针)。请尝试以下方法:

    typedef void (abc::*fptr)(int) const; // won't compile without const (good!)
    std::tr1::bind((fptr)&abc::hello, &x , _1)(a);
    

    正如我在下面的评论中发现的,如果您省略 & 正如您最初所做的,您将通过x 按价值 bind

        2
  •  1
  •   Nicola Bonelli    17 年前

    正如John所说,这些代码片段中出现的问题如下:

    1. 路过 成员函数指针
    2. bind() 是按值传递的参数。

        std::tr1::bind(static_cast< void(abc::*)(int) const >(&abc::hello), x, _1)(a);
    

    第二个问题可以通过按地址传递可调用对象(如John所建议的)或通过TR1来解决 reference_wrapper<> --否则它将按值传递,使 持续性幻觉 .

    给定x一个可调用对象:

    std::tr1::bind( std::tr1::ref(x) , _1)(a);
    

    将向前 a 恰到好处 operator() 根据x .

        3
  •  1
  •   coppro    17 年前

    这个问题已经得到了回答,但我发现使用bind指定重载的最佳方法是在模板上指定它:

    std::tr1::bind<void(foo::*)(int)>(&foo::bar);
    

    此方法同样明确,但比casting(使用 static_cast