作用:将复杂的未知表达式折叠为已知的简单表达式
引用折叠规则遵循以下几个原则:
- 如果两个模板参数都是左值引用(Lvalue references),结果是一个左值引用。
- 如果一个模板参数是左值引用,而另一个是右值引用(Rvalue reference),结果是一个右值引用。
- 如果两个模板参数都是右值引用,即使它们的类型不同,结果仍然是一个右值引用。
#include <iostream>
template<typename T>
void foo(T&& val) {
std::cout << "foo(T&&): 传入的参数是右值引用" << std::endl;
}
template<typename T>
void foo(T& val) {
std::cout << "foo(T&): 传入的参数是左值引用" << std::endl;
}
int main() {
int x = 42;
const int& y = x;
foo(x); // 调用 foo(T&)
foo(y); // 调用 foo(T&)
foo(123); // 调用 foo(T&&)
return 0;
}
在上面的示例中,我们定义了两个函数模板 foo,分别接受一个左值引用和一个右值引用作为参数。在 main 函数中,我们分别传递了一个左值 x、一个 const 左值引用 y 和一个字面量右值 123 给 foo 函数。
根据引用折叠规则,foo(x) 和 foo(y) 都会调用接受左值引用的函数模板 foo(T&),而 foo(123) 则会调用接受右值引用的函数模板 foo(T&&)。
运行以上代码,输出将是:
这个示例演示了引用折叠的基本原理和使用场景。它使编写通用的函数模板能够更好地处理各种类型的参数,无论是左值还是右值。
#include <iostream> template<typename... Args> void print(Args&&... args) { (std::cout << ... << args) << std::endl; } int main() { int x = 42; double y = 3.14; std::string str = "Hello, World!"; print("x = ", x, ", y = ", y, ", str = ", str); return 0; }在上述代码中,我们定义了一个名为
在函数体内部的
(std::cout << ... << args)使用了 C++17 中的折叠表达式(Fold Expression)。这个折叠表达式使用了逗号操作符和左移操作符,逐个将参数args插入到std::cout流中。通过使用引用折叠,即
Args&&... args,我们可以接受传递给在
main函数中,我们传递了一个整型变量x、一个双精度浮点数变量y,以及一个字符串str给运行以上代码,输出将是:
关于完美转发可以见:
No comments yet.