为什么 std::function 存储对成员函数的调用可以有两种不同的可调用类型
why std::function that store a call to member function can have two different callable type
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int num_;
};
int main ()
{
function<void(const Foo*, int)> func = &Foo::print_add;
function<void(const Foo&, int)> func2 = &Foo::print_add;
Foo f(1), f2(2);
func(&f, 2);
func2(f2, 3);
return 0;
}
为什么func
和func2
都可以正确调用成员函数Foo::print_add
?它们具有不同的可调用类型作为模板参数。据我所知,“this”指针作为隐藏参数传递给所有非静态成员函数调用,func2 的可调用类型接收 const Foo&
作为与 this
指针类型不匹配的参数。为什么上面的代码不会产生编译器错误?
why func and func2 both can call member function Foo::print_add correctly?
他们可以,因为标准说他们可以。
From what I know, ‘this’ pointer is passed as a hidden argument
从语言的角度来看,没有“隐藏指针传递”。一个函数被称为“在”一个对象上,this
只是一个关键字,它产生指向该对象的指针。考虑到符号 not_a_pointer.member_function(other_arguments)
似乎没有指针在语法上被传递。
在语言之下,从实现的角度来看(即传递“隐藏”的东西),引用和指针生成的代码没有区别。它们只是内存地址。
顺便说一句:如果 this
生成一个引用而不是一个指针会方便得多。据我了解,成员函数和 this
是在添加引用之前添加到语言中的,因此在那时引用不是一个选项。之后,对语言的这种更改将向后不兼容。
std::function
存储并可以 "invoke any CopyConstructible Callable target".
Callable named requirement定义如下:
if f is a pointer to member function of class T:
If std::is_base_of<T, std::remove_reference_t<decltype(t1)>>::value
is true, then INVOKE(f, t1, t2, ..., tN) is equivalent to
(t1.*f)(t2, ..., tN)
或者,换句话说:如果在删除第一个参数上的任何引用限定符后,最终结果是成员函数的 class(或子 class),则调用成员函数class.
的实例
otherwise, if t1 does not satisfy the previous items,
then INVOKE(f, t1, t2, ..., tN) is equivalent to
((*t1).*f)(t2, ..., tN).
否则:祈祷吧,希望第一个参数是指向成员函数 class 实例的指针,并通过给定的指针调用它(希望它是一个指针,或其他东西)假装它是一个指针)。
最终结果:两者等价。
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int num_;
};
int main ()
{
function<void(const Foo*, int)> func = &Foo::print_add;
function<void(const Foo&, int)> func2 = &Foo::print_add;
Foo f(1), f2(2);
func(&f, 2);
func2(f2, 3);
return 0;
}
为什么func
和func2
都可以正确调用成员函数Foo::print_add
?它们具有不同的可调用类型作为模板参数。据我所知,“this”指针作为隐藏参数传递给所有非静态成员函数调用,func2 的可调用类型接收 const Foo&
作为与 this
指针类型不匹配的参数。为什么上面的代码不会产生编译器错误?
why func and func2 both can call member function Foo::print_add correctly?
他们可以,因为标准说他们可以。
From what I know, ‘this’ pointer is passed as a hidden argument
从语言的角度来看,没有“隐藏指针传递”。一个函数被称为“在”一个对象上,this
只是一个关键字,它产生指向该对象的指针。考虑到符号 not_a_pointer.member_function(other_arguments)
似乎没有指针在语法上被传递。
在语言之下,从实现的角度来看(即传递“隐藏”的东西),引用和指针生成的代码没有区别。它们只是内存地址。
顺便说一句:如果 this
生成一个引用而不是一个指针会方便得多。据我了解,成员函数和 this
是在添加引用之前添加到语言中的,因此在那时引用不是一个选项。之后,对语言的这种更改将向后不兼容。
std::function
存储并可以 "invoke any CopyConstructible Callable target".
Callable named requirement定义如下:
if f is a pointer to member function of class T: If std::is_base_of<T, std::remove_reference_t<decltype(t1)>>::value is true, then INVOKE(f, t1, t2, ..., tN) is equivalent to (t1.*f)(t2, ..., tN)
或者,换句话说:如果在删除第一个参数上的任何引用限定符后,最终结果是成员函数的 class(或子 class),则调用成员函数class.
的实例otherwise, if t1 does not satisfy the previous items, then INVOKE(f, t1, t2, ..., tN) is equivalent to ((*t1).*f)(t2, ..., tN).
否则:祈祷吧,希望第一个参数是指向成员函数 class 实例的指针,并通过给定的指针调用它(希望它是一个指针,或其他东西)假装它是一个指针)。
最终结果:两者等价。