tr1 :: mem_fn和tr1 :: bind:关于const-correctness和重载

时间:2008-11-21 21:52:48

标签: c++ c++11 functional-programming tr1

以下代码段有什么问题?

#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;
}

尝试用g ++ - 4.3编译它,似乎 cv - 限定符重载函数混淆了tr1::mem_fn<>tr1::bind<>,它出现了以下错误:

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

相反,以下代码段会编译但似乎打破 const-correctness

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 个答案:

答案 0 :(得分:3)

查找是在this的常量未知时完成的。你只需要通过施法给它一个提示。试试这个:

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

您可能还会注意到删除const仍然有效。这是因为你应该通过指针传递x(因为C ++成员函数的第一个参数,隐式this参数,总是一个指针)。试试这个:

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

正如我在下面的评论中发现的那样,如果你原来省略了&,那么你将按价值传递x ,这通常不是你想要的(虽然它在你的特定例子中几乎没有实际意义)。这实际上似乎是bind的一个不幸的陷阱。

答案 1 :(得分:1)

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

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

这个方法同样明确,但比铸造更短(无论如何都使用static_cast。但它比C-cast更清晰,长度相同。

答案 2 :(得分:0)

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

  1. 传递成员函数指针时,必须指定其签名(如果超载)
  2. bind()按值传递参数。
  3. 第一个问题是通过强制提供绑定的成员函数指针来解决的:

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

    第二个可以通过按地址传递可调用对象(如John建议的那样)或通过TR1 reference_wrapper<>来解决 - 否则它将通过值传递,使 const-correctness中断幻觉

    给定x可调用对象:

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

    bind()会根据x constness a转发给正确的operator()