Когда мне нужно: std:: forward вызов функции?
Фрагмент кода, который я видел в Effective Modern С++, имеет умную реализацию обоснования инструментария, чтобы создать таймер функции:
auto timeFuncInvocation =
[](auto&& func, auto&&... params)
{
start timer;
std::forward<decltype(func)>(func)(
std::forward<decltype(params)>(params)...);
stop timer and record elapsed time;
};
Мой вопрос о std::forward<decltype(func)>(func)(...
- По моему мнению, мы фактически отбрасываем функцию до ее первоначального типа, но зачем это нужно? Похоже, что простой вызов будет делать трюк.
- Есть ли другие случаи, когда мы используем совершенную переадресацию для вызова функции?
Это выглядит как хороший вариант использования использования знакомого синтаксиса шаблонов в лямбда-выражениях, если мы хотим сделать тип таймера постоянной времени компиляции.
Ответы
Ответ 1
Лучшее описание того, что делает std::forward<decltype(func)>(func)(...)
, будет сохранение категории значений аргумента, переданного лямбда.
Рассмотрим следующий функтор с ref-квалифицированными перегрузками operator()
.
struct foo
{
void operator()() const &&
{ std::cout << __PRETTY_FUNCTION__ << '\n'; }
void operator()() const &
{ std::cout << __PRETTY_FUNCTION__ << '\n'; }
};
Помните, что в теле лямбда func
есть значение lvalue (потому что оно имеет имя). Если вы не указали forward
аргумент функции, то нельзя использовать вызываемую перегрузку &&
. Более того, если квалифицированная перегрузка &
отсутствовала, то даже если вызывающий передал вам экземпляр rvalue foo
, ваш код не смог бы скомпилироваться.
Живая демонстрация