Когда я должен std:: пересылать вызов функции?
Фрагмент кода, который я видел в Effective Modern C++, имеет разумную реализацию инструментария для создания таймера функции:
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-qualified operator()
Перегрузки.
struct foo
{
void operator()() const &&
{ std::cout << __PRETTY_FUNCTION__ << '\n'; }
void operator()() const &
{ std::cout << __PRETTY_FUNCTION__ << '\n'; }
};
Помните, что в теле лямбды func
является lvalue ( потому что у него есть имя). Если вы этого не сделали forward
аргумент функции &&
квалифицированная перегрузка никогда не может быть вызвана. Более того, если &
квалифицированная перегрузка отсутствовала, тогда даже если вызывающий абонент передал вам значение foo
Например, ваш код не сможет скомпилироваться.