Для «прямых» параметров передавайте через `TP&&` и только `std::forward` параметр
Причина
Если объект должен быть передан дальше другому коду, а не использоваться непосредственно этой функцией, мы хотим, чтобы функция была нечувствительна к const-квалификации и «rvalue-ности» аргумента.
В этом случае, и только в нём, делайте параметр TP&&, где TP — параметр шаблонного типа — это одновременно игнорирует и сохраняет const-квалификацию и «rvalue-ность». Поэтому любой код, использующий TP&&, неявно заявляет, что ему безразличны const-квалификация и «rvalue-ность» переменной (поскольку они игнорируются), но он намерен передать значение дальше другому коду, которому это важно (поскольку они сохраняются). При использовании в качестве параметра TP&& безопасен, потому что любые временные объекты, переданные вызывающим, будут жить в течение всего вызова функции. Параметр типа TP&& фактически всегда должен передаваться далее через std::forward в теле функции.
Пример
Обычно вы передаёте весь параметр (или пачку параметров, используя ...) ровно один раз по каждому статическому пути управления:
template<class F, class... Args>
inline decltype(auto) invoke(F&& f, Args&&... args)
{
return forward<F>(f)(forward<Args>(args)...);
}
Пример
Иногда вы можете передавать составной параметр по частям, каждый подобъект по одному разу по каждому статическому пути управления:
template<class PairLike>
inline auto test(PairLike&& pairlike)
{
// ...
f1(some, args, and, forward<PairLike>(pairlike).first); // передаём .first
f2(and, forward<PairLike>(pairlike).second, in, another, call); // передаём .second
}
Контроль
- Помечать функцию, принимающую параметр
TP&&(гдеTP— имя параметра шаблонного типа) и делающую с ним что-либо, кромеstd::forward-а ровно один раз по каждому статическому пути, или делающейstd::forwardболее одного раза, но квалифицированной другим членом-данным ровно один раз по каждому статическому пути.