我很好奇为什么a2可以,但b2无法编译:
#include <functional>
#include <iostream>
class A {
public:
A(std::function<void(int)>&& func) : f(std::move(func)) {}
std::function<void(int)> f;
};
template <class F>
class B {
public:
B(F&& func) : f(std::move(func)) {}
F f;
};
int main() {
int a = 1;
auto f = [a](int b){std::cout << a+b << '\n';};
A a1([a](int b){std::cout << a+b << '\n';});
A a2(f);
B b1([a](int b){std::cout << a+b << '\n';});
// B b2(f);
a1.f(2);
a2.f(2);
b1.f(2);
// b2.f(2);
f(2);
}
Run Code Online (Sandbox Code Playgroud)
A(std::function<void(int)>&& func)
Run Code Online (Sandbox Code Playgroud)
A可以用std::function右值初始化。现在,f(in main)不是a std::function,因为每个 lambda 都有其自己不同的类型。但是我们可以创建一个临时std::function的,并将右值引用绑定func到它。
B(F&& func)
Run Code Online (Sandbox Code Playgroud)
不要让外表欺骗了你。这可能看起来像转发参考,但事实并非如此。从语法上讲,转发引用是对模板参数的右值引用,但它必须是我们要转发到的函数的模板参数。
的构造函数B不是模板,因此func不是转发引用。
从该构造函数生成的推导指南仅接受右值,并F从中进行推导。因为f( 中的本地 lambda main) 是左值,所以它无法绑定到右值引用,因此 CTAD 无法成功。确实std::move(f)会使得b2格式良好。
如果您还想接受参数的左值,您可以添加另一个构造函数
B(F const& func) : f(func) {}
Run Code Online (Sandbox Code Playgroud)
现在正在生成两个演绎指南,每个值类别一个。
| 归档时间: |
|
| 查看次数: |
126 次 |
| 最近记录: |