std::bind 如何按值获取可变参数,即使它具有通用引用?
How does std::bind take variadic arguments by value, even with its universal reference?
std::bind()
is as follows的函数签名:
template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
所以args
是一个可变参数模板通用引用,如果我没理解错的话。通用引用的传统模板类型推导规则如下:
- 如果传递给 T 的参数是左值,则 T 被推导为左值引用
- 如果传递给 T 的参数是右值,则 T 被推导为左值
... 我认为这些规则将单独应用于 args
中的每个 arg,这意味着作为参数传递给 std::bind()
的所有左值都将通过引用传递。然而,这与下面的程序相矛盾:
#include <iostream>
#include <functional>
void function(int& n) {
n++;
}
int main() {
int n = 0;
auto functor = std::bind(function, n);
functor();
std::cout << n << std::endl; // 0, not 1.
return 0;
}
为了让 n
通过引用传递,您必须通过 std::ref(n)
明确地这样做,考虑到我对通用引用和完美转发的了解(很少),这真的让我感到困惑。 std::bind()
在使用通用引用时如何按值取值,否则通用引用会使用左值作为引用?
和签名几乎没有关系,是一种设计选择。 std::bind
当然必须以某种方式存储所有绑定参数,并将它们存储为值。 “通用性”仅用于正确构造它们 - 通过移动或复制。
std::ref
也是按值存储,但由于其性质,包装对象是按引用“存储”的。
std::thread
具有完全相同的行为。可以争辩说(移动)默认构造一个副本更安全,因为两个返回的对象往往比最有可能被捕获的本地对象活得更久。
std::bind()
is as follows的函数签名:
template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
所以args
是一个可变参数模板通用引用,如果我没理解错的话。通用引用的传统模板类型推导规则如下:
- 如果传递给 T 的参数是左值,则 T 被推导为左值引用
- 如果传递给 T 的参数是右值,则 T 被推导为左值
... 我认为这些规则将单独应用于 args
中的每个 arg,这意味着作为参数传递给 std::bind()
的所有左值都将通过引用传递。然而,这与下面的程序相矛盾:
#include <iostream>
#include <functional>
void function(int& n) {
n++;
}
int main() {
int n = 0;
auto functor = std::bind(function, n);
functor();
std::cout << n << std::endl; // 0, not 1.
return 0;
}
为了让 n
通过引用传递,您必须通过 std::ref(n)
明确地这样做,考虑到我对通用引用和完美转发的了解(很少),这真的让我感到困惑。 std::bind()
在使用通用引用时如何按值取值,否则通用引用会使用左值作为引用?
和签名几乎没有关系,是一种设计选择。 std::bind
当然必须以某种方式存储所有绑定参数,并将它们存储为值。 “通用性”仅用于正确构造它们 - 通过移动或复制。
std::ref
也是按值存储,但由于其性质,包装对象是按引用“存储”的。
std::thread
具有完全相同的行为。可以争辩说(移动)默认构造一个副本更安全,因为两个返回的对象往往比最有可能被捕获的本地对象活得更久。