为什么从std :: mem_fn返回的可调用对象可以用在对象和shared_ptrs上?

时间:2017-01-10 13:20:16

标签: c++ c++11 c++14

以下代码works,但我不明白为什么会这样做。

#include <functional>
#include <iostream>
#include <memory>

struct foo
{
    int get_val() const
    {
        return 42;
    }
};

int main()
{
    foo obj;
    std::shared_ptr<foo> ptr = std::make_shared<foo>();

    const auto getter = std::mem_fn( &foo::get_val );

    std::cout << getter( obj ) << std::endl;
    std::cout << getter( ptr ) << std::endl;
}

为什么可以在getterobj上使用ptr?我希望它只适用于obj

3 个答案:

答案 0 :(得分:3)

来自std::mem_fn cppreference page

  

函数模板std::mem_fn为成员指针生成包装器对象,可以存储,复制和调用指向成员的指针。 调用std::mem_fn 时,可以使用对象的引用和指针(包括智能指针)。

简短回答:因为标准是这么说的。

我想这只是一个更方便和通用的界面,例如,您可以编写一个调用std::mem_fn模板函数,它将同时适用于引用和指针:

const auto getter = std::mem_fn( &foo::get_val );

template <typename T>
void call_getter(T&& x)
{
    // do something
    getter(x);
    // do something
}

int main()
{
    foo obj;
    std::shared_ptr<foo> ptr = std::make_shared<foo>();

    call_getter( obj );
    call_getter( ptr );
}

在上面的示例中,您只需要一次call_getter的重载。

答案 1 :(得分:3)

mem_fn是根据可调用的概念定义的,就像标准中的许多其他内容一样(functionasyncreference_wrapper等等。

可调用概念是根据标准中的INVOKE定义的。

在这种情况下,

INVOKE缩小为:

  

否则,如果t1不满足之前的项目,则INVOKE(f, t1, t2, ..., tN)相当于((*t1).*f)(t2, ..., tN)

(引用来源:cppreference.com),其中f是您传递的内容mem_fnt1...tn是您传递mem_fn的返回值的算法。

((*smart_ptr).*mem_fun)(args...)有效。所以它有效。

不那么直接,因为编写标准的人意味着它可以工作。

答案 2 :(得分:2)

来自this std::mem_fn reference

  

调用std::mem_fn

时,可以使用对象的引用和指针(包括智能指针)

它只是意味着对象std::mem_fn具有函数调用操作符的重载,它将实例和指针(正常和智能)都带到对象的实例以调用函数。