以下代码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;
}
为什么可以在getter
和obj
上使用ptr
?我希望它只适用于obj
。
答案 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
是根据可调用的概念定义的,就像标准中的许多其他内容一样(function
,async
,reference_wrapper
等等。
可调用概念是根据标准中的INVOKE
定义的。
INVOKE
缩小为:
否则,如果t1不满足之前的项目,则
INVOKE(f, t1, t2, ..., tN)
相当于((*t1).*f)(t2, ..., tN)
。
(引用来源:cppreference.com),其中f
是您传递的内容mem_fn
。 t1...tn
是您传递mem_fn
的返回值的算法。
((*smart_ptr).*mem_fun)(args...)
有效。所以它有效。
不那么直接,因为编写标准的人意味着它可以工作。
答案 2 :(得分:2)
调用
时,可以使用对象的引用和指针(包括智能指针)std::mem_fn
它只是意味着对象std::mem_fn
具有函数调用操作符的重载,它将实例和指针(正常和智能)都带到对象的实例以调用函数。