Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Purpose of perfect forwarding for Callable argument in invocation expression?

In Scott Meyer's book Effective Modern C++ on page 167 (of the print version), he gives the following example:

auto timeFuncInvocation = [](auto&& func, auto&&... params) {
  // start timer;
  std::forward<decltype(func)>(func)(
    std::forward<decltype(params)>(params)...
  );
  // stop timer and record elapsed time;
};

I completely understand the perfect forwarding of params, but it is unclear to me when perfect forwarding of func would ever be relevant. In other words, what are the advantages of the above over the following:

auto timeFuncInvocation = [](auto&& func, auto&&... params) {
  // start timer;
  func(
    std::forward<decltype(params)>(params)...
  );
  // stop timer and record elapsed time;
};
like image 802
Daisy Sophia Hollman Avatar asked Apr 28 '16 16:04

Daisy Sophia Hollman


People also ask

Why do we need perfect forwarding?

Perfect forwarding reduces excessive copying and simplifies code by reducing the need to write overloads to handle lvalues and rvalues separately. Note: The function the arguments are forwarded to can be a normal function, another template function, or a constructor.

What is the purpose of std :: forward?

std::forward helps to implement perfect forwarding. This mechanism implies that objects passed to the function as lvalue expressions should be copied, and objects passed to the function as rvalue expressions should be moved. If you assign an rvalue reference to some ref variable, then ref is a named entity.

What is perfect forwarding?

Perfect forwarding makes it possible to write function templates that take arbitrary arguments and forward them to other functions such that the target functions receive exactly the same arguments as were passed to the forwarding functions.

What is a forwarding reference?

I understand that a forwarding reference is "an rvalue reference to a cv-unqualified template parameter", such as in. template <class T> void foo(T&& ); which means the above function can take both l-value and r-value reference.


1 Answers

For the same purpose as for arguments: so when Func::operator() is a ref-qualified:

struct Functor
{
    void operator ()() const &  { std::cout << "lvalue functor\n"; }
    void operator ()() const && { std::cout << "rvalue functor\n"; }
};

Demo

like image 116
Jarod42 Avatar answered Oct 12 '22 23:10

Jarod42