std::function 的模板参数如何工作? (执行)
在 Bjarne Stroustrup 的主页中 (C++ 11 常见问题解答):
struct X { int foo(int); };
std::function<int(X*, int)> f;
f = &X::foo; //pointer to member
X x;
int v = f(&x, 5); //call X::foo() for x with 5
它是如何工作的? std::function 如何调用 foo 成员函数?
模板参数是int(X*, int)
,是&X::foo
从成员函数指针转换为 >非成员函数指针?!
(int(*)(X*, int))&X::foo //casting (int(X::*)(int) to (int(*)(X*, int))
澄清一下:我知道我们不需要转换任何指针来使用 std::function ,但我不知道 std::function 的内部结构如何处理成员函数指针和非成员函数指针之间的不兼容性。我不知道标准如何允许我们实现像 std::function 这样的东西!
In Bjarne Stroustrup's home page (C++11 FAQ):
struct X { int foo(int); };
std::function<int(X*, int)> f;
f = &X::foo; //pointer to member
X x;
int v = f(&x, 5); //call X::foo() for x with 5
How does it work? How does std::function call a foo member function?
The template parameter is int(X*, int)
, is &X::foo
converted from the member function pointer to a non-member function pointer?!
(int(*)(X*, int))&X::foo //casting (int(X::*)(int) to (int(*)(X*, int))
To clarify: I know that we don't need to cast any pointer to use std::function, but I don't know how the internals of std::function handle this incompatibility between a member function pointer and a non-member function pointer. I don't know how the standard allows us to implement something like std::function!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在获得其他答案和评论的帮助,并阅读 GCC 源代码和 C++11 标准后,我发现可以解析函数类型(其返回类型及其参数类型)通过使用部分模板专业化和
函数重载。
以下是一个简单(且不完整)的示例,用于实现 std::function 之类的内容:
用法:
After getting help from other answers and comments, and reading GCC source code and C++11 standard, I found that it is possible to parse a function type (its return type and its argument types) by using partial template specialization and
function overloading.
The following is a simple (and incomplete) example to implement something like
std::function
:Usage:
它是如何做到的(我相信)尚未定义(但我这里没有标准的副本)。
但考虑到需要涵盖的所有不同可能性,我感觉破译其工作原理的确切定义将非常困难:所以我不会尝试。
但我想你想知道函子是如何工作的,而且它们相对简单。这是一个简单的例子。
函子:
这些对象的行为类似于函数。
它们在模板代码中非常有用,因为它们通常允许您互换使用对象或函数。函子的伟大之处在于它们可以保存状态(一种穷人的闭包)。
您可以使用函子保持状态来保存参数、对象或指向成员方法的指针(或其任意组合)等内容。
或者甚至更进一步绑定参数。所以现在您需要提供的只是参数之一。
How it does it (I believe) is left undefined (but I don't have a copy of the standard here).
But given all the different possibilities that need to be covered I have the feeling that deciphering the exact definition of how it works would be really hard: So I am not going to try.
But I think you would like to know how functors work and they are relatively simple. So here is a quick example.
Functors:
These are objects that act like functions.
They are very useful in template code as they often allow you to use objects or functions interchangeably. The great thing about functors though is that they can hold state (a sort of poor man's closure).
You can use the fact that functor hold state to hold things like parameters or the objects or the pointer to member methods (or any combination thereof).
Or even go further and bind parameters. So now all you need to provide is one of the parameters.
来回答一下标题中的问题。
std::function
使用的参数是一个很好的技巧,可以将许多类型参数作为单个模板参数传递。这些参数是函数的参数类型和返回类型。事实证明,std::function 尝试对通用函子进行类型擦除,但这只是巧合。
事实上,从前有一些编译器不接受这样的技巧,而
boost::function
的前身有一个可移植语法,所有参数都通过该语法可以单独传递:https://www.boost.org/doc/libs/1_68_0/doc/html/function/tutorial.html#id-1.3.16.5.4
这就是
std:: 的模板参数: function
工作,最终它只是一个技巧,让很多参数看起来像函数调用。指向该类型函数的函数指针不一定包含在类中。To answer the question in the title. The parameter that
std::function
uses is a nice trick to pass many type parameters as a single template parameter. Those arguments being the argument types and the return type of a function.It turns out that
std::function
tries to type-erase a general functor but that is just coincidence.As a matter of fact, once upon a time there were compilers that wouldn't accept such tricks and the
boost::function
precursor had a portable syntax by which all the parameters could be passed separately:https://www.boost.org/doc/libs/1_68_0/doc/html/function/tutorial.html#id-1.3.16.5.4
So that's how the template parameters of
std::function
work, at the end it is just a trick to make a lot of parameters look like a function call. Function pointers to that type of function are not necessarily involved in the class.它们不是函数指针。这就是 std::function 存在的目的。它包装了您提供的任何可调用类型。您应该查看 boost::bind - 它通常用于使成员函数指针可调用为 (this, args)。
They're not function pointers. That's what std::function exists for. It wraps whatever callable types you give it. You should check out boost::bind- it's often used to make member function pointers callable as (this, args).
g++ 似乎有一个联合体,可以保留函数指针、成员指针或可能指向函子的 void 指针。添加重载,适当地标记哪个联合成员是有效的,并对汤进行重铸,然后它就可以工作了......
g++ seems to have an union which may keep either function pointer, member pointer or void pointer which probably points to a functor. Add overloads which appropriately flag which union member is valid and heavy casting to a soup and then it works...