Как правильно написать функцию принимающую универсальную ссылку?

В C++11 была введена новая особенность языка - "универсальные ссылки" или "ссылки на rvalue-ссылки", которая позволяет передавать аргументы функции без потери эффективности и с поддержкой перемещения (move semantics).

Универсальная ссылка обозначается с помощью двойного амперсанда (&&) и может привязываться к обоим lvalue и rvalue. Когда универсальная ссылка связывается с rvalue, она позволяет использовать move semantics, а при связывании с lvalue - приведение lvalue к rvalue.

Правильно написать функцию, принимающую универсальную ссылку, можно следующим образом:

template <typename T>
void foo(T&& arg) {
    // Внутри функции аргумент "arg" может использоваться как lvalue,
    // так и rvalue в зависимости от объекта, переданного при вызове функции.

    // Примеры использования универсальной ссылки:
    // 1. Копирование/перемещение аргумента "arg"
    T copy(std::forward<T>(arg));

    // 2. Обработка аргумента "arg"
    process(std::forward<T>(arg));

    // 3. Приведение аргумента "arg" к rvalue
    rvalue_func(std::move(arg));
}

В приведенном примере шаблонная функция foo принимает универсальную ссылку arg типа T&&. T - это тип аргумента, который будет выведен компилятором при вызове функции. Внутри функции можно использовать arg и передавать его другим функциям, применяя std::forward для сохранения обратной совместимости со значением lvalue или rvalue.

Важно отметить, что при передаче lvalue-аргумента (T&), T будет выведен как T&, а при передаче rvalue-аргумента (T&&), T будет выведен как T без ссылки. Это позволяет использовать механизм move semantics или приведение lvalue к rvalue внутри функции, что может быть полезно для оптимизации и обработки временных объектов.