Когда я должен 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 Например, ваш код не сможет скомпилироваться.

Живая демо

Другие вопросы по тегам