std::forward


Function: std::forward

std::forward is a utility function in C++ that is primarily used in the context of perfect forwarding. Perfect forwarding is a technique where a function template passes its arguments to another function in such a way that the argument's value category (whether it's an lvalue or rvalue) is preserved. This is particularly useful when writing generic code, such as in function templates or variadic templates, where you want to ensure that arguments are forwarded exactly as they were received.

Key Concepts of std::forward

Basic Syntax

The syntax for std::forward is:

std::forward<T>(arg);

where - T: The template type parameter, typically deduced in the context of perfect forwarding. - arg: The argument to be forwarded.

Why Use std::forward?

When you have a function template that takes a forwarding reference (e.g., T&&), you want to ensure that if an rvalue is passed to this function, it remains an rvalue when passed on to another function. Similarly, if an lvalue is passed, it should remain an lvalue.

Example 1: Perfect Forwarding with std::forward

Here's a simple example to illustrate how std::forward preserves the value category of an argument.

#include <iostream>
#include <utility>  // for std::forward

void process(int& x) {
    std::cout << "Lvalue reference: " << x << std::endl;
}

void process(int&& x) {
    std::cout << "Rvalue reference: " << x << std::endl;
}

template<typename T>
void forwarder(T&& arg) {
    process(std::forward<T>(arg));  // Forward the argument with its original value category
}

int main() {
    int a = 10;

    forwarder(a);          // Calls process(int&), lvalue reference
    forwarder(20);         // Calls process(int&&), rvalue reference
    forwarder(std::move(a));  // Calls process(int&&), rvalue reference

    return 0;
}

Explanation:

In main, you can see that std::forward allows the forwarder function to pass a, 20, and std::move(a) to process with their original value categories preserved.

Example 2: Using std::forward in Variadic Templates

std::forward is especially useful in variadic templates, where you might want to forward a variable number of arguments to another function.

#include <iostream>
#include <utility>

void process(int& x) {
    std::cout << "Lvalue reference: " << x << std::endl;
}

void process(int&& x) {
    std::cout << "Rvalue reference: " << x << std::endl;
}

template<typename... Args>
void variadicForwarder(Args&&... args) {
    (process(std::forward<Args>(args)), ...);  // Fold expression to call process on each argument
}

int main() {
    int a = 10;
    variadicForwarder(a, 20, std::move(a));

    return 0;
}

Explanation:

Example 3: std::forward in Factory Functions

std::forward is often used in factory functions, where you want to construct objects by perfectly forwarding arguments to constructors.

#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass(int x) {
        std::cout << "MyClass constructed with " << x << std::endl;
    }
};

template<typename T, typename... Args>
std::unique_ptr<T> make_unique_custom(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

int main() {
    auto obj = make_unique_custom<MyClass>(42);

    return 0;
}

Explanation:

Common Pitfalls

Summary

Previous Page | Course Schedule | Course Content