C++完美转发与引用折叠
C++完美转发与引用折叠
完美转发保持参数的值类别,确保资源所有权正确传递。引用折叠规则决定模板参数推导后的引用类型。这两者是实现通用包装器的关键技术。
引用折叠规则确定最终引用类型。
#include
#include
#include
#include
template
void show_category(T&& arg) {
if constexpr (std::is_lvalue_reference_v) {
std::cout << "Lvalue reference (T = T&)\n";
} else if constexpr (std::is_rvalue_reference_v) {
std::cout << "Rvalue reference (T = T&&)\n";
} else {
std::cout << "Not a reference\n";
}
}
void reference_folding() {
int x = 42;
std::cout << "Call with lvalue: ";
show_category(x);
std::cout << "Call with rvalue: ";
show_category(100);
}
std::forward保持值类别进行转发。
void process(int& x) {
std::cout << "Lvalue: " << x << "\n";
}
void process(int&& x) {
std::cout << "Rvalue: " << x << "\n";
}
template
void forwarder(T&& arg) {
process(std::forward(arg));
}
void forwarding_demo() {
int x = 10;
std::cout << "Forwarding lvalue: ";
forwarder(x);
std::cout << "Forwarding rvalue: ";
forwarder(20);
}
完美转发在工厂函数中的应用。
template
std::unique_ptr make_unique_fwd(Args&&... args) {
return std::unique_ptr(new T(std::forward(args)...));
}
class Widget {
std::string name_;
int value_;
public:
Widget(const std::string& name, int v)
: name_(name), value_(v) {
std::cout << "Widget(const string&)\n";
}
Widget(std::string&& name, int v)
: name_(std::move(name)), value_(v) {
std::cout << "Widget(string&&)\n";
}
void show() const {
std::cout << name_ << ": " << value_ << "\n";
}
};
void factory_demo() {
std::string s = "test";
auto w1 = make_unique_fwd(s, 42);
w1->show();
auto w2 = make_unique_fwd(std::string("temp"), 100);
w2->show();
}
可变参数模板与完美转发结合。
template
void print_all(Args&&... args) {
(std::cout << ... << std::forward(args)) << "\n";
}
void variadic_forward() {
print_all("Hello", " ", "World", " ", 42, " ", 3.14);
}
完美转发包装器。
template
decltype(auto) call_wrapper(Func&& func, Args&&... args) {
std::cout << "Before call\n";
if constexpr (std::is_void_v(args)...))>) {
func(std::forward(args)...);
std::cout << "After call (void)\n";
} else {
auto result = func(std::forward(args)...);
std::cout << "After call (non-void)\n";
return result;
}
}
int add(int a, int b) {
return a + b;
}
void say_hello(const std::string& name) {
std::cout << "Hello, " << name << "!\n";
}
void wrapper_demo() {
int result = call_wrapper(add, 10, 20);
std::cout << "Result: " << result << "\n";
call_wrapper(say_hello, "Alice");
}
引用折叠的四种情况。
template
void fold_examples() {
using lref = T&;
using rref = T&&;
using T1 = lref&;
using T2 = lref&&;
using T3 = rref&;
using T4 = rref&&;
std::cout << "T& & -> T&: " << std::is_same_v << "\n";
std::cout << "T& && -> T&: " << std::is_same_v << "\n";
std::cout << "T&& & -> T&: " << std::is_same_v << "\n";
std::cout << "T&& && -> T&&: " << std::is_same_v << "\n";
}
void folding_rules() {
fold_examples();
}
完美转发在emplace_back中的应用。
class Expensive {
std::string data_;
public:
Expensive(const std::string& d) : data_(d) {
std::cout << "Copy string\n";
}
Expensive(std::string&& d) : data_(std::move(d)) {
std::cout << "Move string\n";
}
};
void emplace_demo() {
std::vector vec;
std::string s = "Hello";
std::cout << "push_back with copy:\n";
vec.push_back(Expensive(s));
std::cout << "emplace_back with move:\n";
vec.emplace_back(std::move(s));
}
转发引用与auto&&。
void auto_forward() {
auto&& forwarded = []() -> int { return 42; }();
std::cout << "Forwarded: " << forwarded << "\n";
}
完美转发是现代C++泛型库开发的基础技术。
