使用 std::function 调用非指针对象的成员函数
Member functions called on non-pointer objects with std::function
代码如下
std::string::empty()
应该以this
指针为参数,类型为指针、std::string *
.
2
和 3
行的调用怎么可能正常?
#include <iostream>
#include <functional>
int main() {
std::string str{"A small pond"};
std::function<bool(std::string*)> fp = &std::string::empty;
std::cout << fp(&str) << std::endl; // 1
std::function<bool(std::string)> f = &std::string::empty;
std::cout << f(str) << std::endl; // 2
std::function<bool(std::string&)> fr = &std::string::empty;
std::cout << fr(str) << std::endl; // 3
}
/*
output:
0
0
0
*/
clang version 9.0.0-2~ubuntu18.04.2 (tags/RELEASE_900/final)
g++ (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0
std::function
可以接受任何匹配其类型签名的 Callable。调用时,可调用对象和参数根据以下规则进行评估(引用 cppreference):
- If
f
is a pointer to member function of class T
:
- If
std::is_base_of<T, std::decay_t<decltype(t1)>>::value
is true
, then INVOKE(f, t1, t2, ..., tN)
is equivalent to
(t1.*f)(t2, ..., tN)
- If
std::decay_t<decltype(t1)>
is a specialization of std::reference_wrapper
, then INVOKE(f, t1, t2, ..., tN)
is
equivalent to (t1.get().*f)(t2, ..., tN)
- If
t1
does not satisfy the previous items, then INVOKE(f, t1, t2, ..., tN)
is equivalent to ((*t1).*f)(t2, ..., tN)
.
所以第一种情况的评估方式类似于 (*t1).*f()
,而其他两种情况的评估方式类似于 t1.*f()
。
代码如下
std::string::empty()
应该以this
指针为参数,类型为指针、std::string *
.
2
和 3
行的调用怎么可能正常?
#include <iostream>
#include <functional>
int main() {
std::string str{"A small pond"};
std::function<bool(std::string*)> fp = &std::string::empty;
std::cout << fp(&str) << std::endl; // 1
std::function<bool(std::string)> f = &std::string::empty;
std::cout << f(str) << std::endl; // 2
std::function<bool(std::string&)> fr = &std::string::empty;
std::cout << fr(str) << std::endl; // 3
}
/*
output:
0
0
0
*/
clang version 9.0.0-2~ubuntu18.04.2 (tags/RELEASE_900/final)
g++ (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0
std::function
可以接受任何匹配其类型签名的 Callable。调用时,可调用对象和参数根据以下规则进行评估(引用 cppreference):
- If
f
is a pointer to member function of classT
:
- If
std::is_base_of<T, std::decay_t<decltype(t1)>>::value
istrue
, thenINVOKE(f, t1, t2, ..., tN)
is equivalent to(t1.*f)(t2, ..., tN)
- If
std::decay_t<decltype(t1)>
is a specialization ofstd::reference_wrapper
, thenINVOKE(f, t1, t2, ..., tN)
is equivalent to(t1.get().*f)(t2, ..., tN)
- If
t1
does not satisfy the previous items, thenINVOKE(f, t1, t2, ..., tN)
is equivalent to((*t1).*f)(t2, ..., tN)
.
所以第一种情况的评估方式类似于 (*t1).*f()
,而其他两种情况的评估方式类似于 t1.*f()
。