首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >tr1::mem_fn和tr1::bind: on const-正确性和重载

tr1::mem_fn和tr1::bind: on const-正确性和重载
EN

Stack Overflow用户
提问于 2008-11-21 21:52:48
回答 3查看 3.2K关注 0票数 5

下面的片段有什么问题?

代码语言:javascript
复制
#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<>,并出现了以下错误:

代码语言:javascript
复制
no matching function for call to ‘bind(<unresolved overloaded function type>,...

相反,下面的代码片段编译,但似乎破坏了const-correctness

代码语言:javascript
复制
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);

有线索吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2008-11-21 22:03:50

查找是在不知道this的稳定性的时候进行的。你只要给它一个提示就行了。试试这个:

代码语言:javascript
复制
typedef void (abc::*fptr)(int) const; // or remove const
std::tr1::bind((fptr)&abc::hello, x , _1)(a);

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

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

正如在下面的注释中所发现的那样,如果您像最初那样省略了&,那么您将按值传递x,这通常不是您想要的结果(尽管它在您的特定示例中几乎没有实际影响)。对于bind来说,这似乎是一个不幸的陷阱。

票数 4
EN

Stack Overflow用户

发布于 2008-11-22 10:07:03

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

在传递成员函数指针时,必须指定其签名(如果overloaded)

  • bind()按值传递参数.

)

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

代码语言:javascript
复制
    std::tr1::bind(static_cast< void(abc::*)(int) const >(&abc::hello), x, _1)(a);

第二个问题可以通过按地址传递可调用对象来解决(如约翰建议的那样),或者通过TR1 reference_wrapper<>来解决--否则它将通过值传递,从而打破了验证正确性的幻觉。

给定x一个可调用对象:

代码语言:javascript
复制
std::tr1::bind( std::tr1::ref(x) , _1)(a);

bind()将根据x常数a转发到适当的operator()

票数 1
EN

Stack Overflow用户

发布于 2008-11-30 07:32:36

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

代码语言:javascript
复制
std::tr1::bind<void(foo::*)(int)>(&foo::bar);

此方法同样显式,但比强制转换(无论如何使用static_cast )要短。但是它比C型更干净,它的长度是一样的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/310333

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档