C ++ 0x показывает пример использования std::forward
:
template<class T>
void foo(T&& arg)
{
bar(std::forward<T>(arg));
}
Когда выгодно использовать std::forward
всегда?
Кроме того, он требует использования &&
в декларации параметров, действительно ли это во всех случаях? Я думал, что вам нужно передать временные функции в функцию, если она была объявлена &&
в ней, так может ли foo вызываться с любым параметром?
Наконец, если у меня есть вызов функции, такой как этот:
template<int val, typename... Params>
void doSomething(Params... args) {
doSomethingElse<val, Params...>(args...);
}
Должен ли я использовать это вместо:
template<int val, typename... Params>
void doSomething(Params&&... args) {
doSomethingElse<val, Params...>(std::forward<Params>(args)...);
}
Кроме того, целесообразно ли использовать параметры в функции дважды, т. Е. Перенаправлять их одновременно двум функциям std::forward
? Не std::forward
преобразует ли одно и то же во временное дважды, перемещая память и делая ее недействительной для повторного использования? Будет ли следующий код в порядке:
template<int val, typename... Params>
void doSomething(Params&&... args) {
doSomethingElse<val, Params...>(std::forward<Params>(args)...);
doSomethingWeird<val, Params...>(std::forward<Params>(args)...);
}
Я немного сбит с толку std::forward
, и я бы с удовольствием воспользовался некоторыми разъяснениями.
источник
Args...&& args
?Ответ Керрека очень полезен, но он не полностью отвечает на вопрос из заголовка:
Чтобы ответить на него, мы должны сначала ввести понятие универсальных ссылок . Скотт Мейерс дал это имя, и в настоящее время их часто называют пересылочными ссылками. В основном, когда вы видите что-то вроде этого:
имейте в виду, что
param
это не ссылка на значение (как можно предположить), а универсальная ссылка *. Универсальные ссылки характеризуются очень ограниченной формой (простоT&&
, без const или аналогичных квалификаторов) и с помощью дедукции типа - типT
будет выведен приf
вызове. В двух словах, универсальные ссылки соответствуют ссылкам rvalue, если они инициализируются с помощью значений rvalue, и ссылкам lvalue, если они инициализируются с помощью значений lvalue.Теперь относительно легко ответить на исходный вопрос - обратиться
std::forward
к:Пример для первого случая:
В приведенном выше коде мы не хотим
prop
иметь какое-то неизвестное значение послеother.set(..)
его завершения, поэтому пересылка здесь не происходит. Тем не менее, когдаbar
мы звоним, мы продвигаемся,prop
как мы закончили с этим, иbar
можем делать с ним все, что захотим (например, переместить его).Пример для второго случая:
Этот шаблон функции должен переместиться
prop
в возвращаемое значение, если оно является rvalue, и скопировать его, если это lvalue. В случае, если мы опускаемstd::forward
в конце, мы всегда создаем копию, которая стоит дороже, когдаprop
оказывается rvalue.* если быть точным, универсальная ссылка - это концепция получения rvalue-ссылки на cv-неквалифицированный параметр шаблона.
источник
Этот пример помогает? Я изо всех сил пытался найти полезный не универсальный пример std :: forward, но натолкнулся на пример банковского счета, на который мы передаем наличные деньги для депонирования в качестве аргумента.
Поэтому, если у нас есть постоянная версия учетной записи, мы должны ожидать, когда передадим ее в наш шаблон депозита <>, что вызывается функция const; и это затем вызывает исключение (идея заключается в том, что это была заблокированная учетная запись!)
Если у нас есть неконстантный аккаунт, мы сможем изменить его.
Строить:
Ожидаемый результат:
источник