5

以下代码段有什么问题?

#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 -qualifier 重载函数混淆了两者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);

有什么线索吗?

4

3 回答 3

4

this查找是在不知道constness 的时候完成的。你只需要通过铸造给它一个提示。试试这个:

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);

正如我在下面的评论中发现的那样,如果您&像原来一样省略了,您将通过 value传递 x ,这通常不是您想要的(尽管在您的特定示例中几乎没有实际差异)。这实际上似乎是一个不幸的陷阱bind

于 2008-11-21T22:03:50.523 回答
1

正如约翰建议的那样,这些片段中出现的问题如下:

  1. 传递成员函数指针时,必须指定其签名(如果重载)
  2. bind()按值传递参数。

第一个问题是通过将提供的成员函数指针转换为绑定来解决的:

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

第二个可以通过按地址传递可调用对象(如约翰建议)或通过 TR1 来解决reference_wrapper<>- 否则它将按值传递,从而使const-correctness 打破幻觉

给定 xa 可调用对象:

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

bind()将根据 x constness转发a到适当的位置。operator()

于 2008-11-22T10:07:03.323 回答
1

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

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

这种方法同样明确,但比强制转换短(static_cast无论如何。但它比 C-cast 更干净,它的长度相同。

于 2008-11-30T07:32:36.317 回答